forked from cockroachdb/cockroach
/
rocksdb.go
112 lines (101 loc) · 3.55 KB
/
rocksdb.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
// Copyright 2017 The Cockroach Authors.
//
// Licensed under the Cockroach Community Licence (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://github.com/cockroachdb/cockroach/blob/master/pkg/ccl/LICENSE
package engineccl
import (
"errors"
"unsafe"
"github.com/cockroachdb/cockroach/pkg/storage/engine"
"github.com/cockroachdb/cockroach/pkg/storage/engine/enginepb"
)
// #cgo CPPFLAGS: -I../../../../vendor/github.com/cockroachdb/c-protobuf/internal/src
// #cgo CPPFLAGS: -I../../../../vendor/github.com/cockroachdb/c-rocksdb/internal/include
// #cgo CXXFLAGS: -std=c++11
// #cgo !strictld,darwin LDFLAGS: -Wl,-undefined -Wl,dynamic_lookup
// #cgo !strictld,!darwin LDFLAGS: -Wl,-unresolved-symbols=ignore-all
// #cgo linux LDFLAGS: -lrt
//
// #include <stdlib.h>
// #include "db.h"
import "C"
// VerifyBatchRepr asserts that all keys in a BatchRepr are between the specified
// start and end keys and computes the enginepb.MVCCStats for it.
func VerifyBatchRepr(
repr []byte, start, end engine.MVCCKey, nowNanos int64,
) (enginepb.MVCCStats, error) {
var stats C.MVCCStatsResult
if err := statusToError(C.DBBatchReprVerify(
goToCSlice(repr), goToCKey(start), goToCKey(end), C.int64_t(nowNanos), &stats,
)); err != nil {
return enginepb.MVCCStats{}, err
}
return cStatsToGoStats(stats, nowNanos)
}
// TODO(dan): The following are all duplicated from storage/engine/rocksdb.go,
// but if you export the ones there and reuse them here, it doesn't work.
//
// `cannot use engine.GoToCSlice(repr) (type engine.C.struct___0) as type C.struct___0 in argument to _Cfunc_DBBatchReprVerify`
//
// At worst, we could split these out into a separate file in storage/engine and
// use `go generate` to copy it here so they stay in sync.
// goToCSlice converts a go byte slice to a DBSlice. Note that this is
// potentially dangerous as the DBSlice holds a reference to the go
// byte slice memory that the Go GC does not know about. This method
// is only intended for use in converting arguments to C
// functions. The C function must copy any data that it wishes to
// retain once the function returns.
func goToCSlice(b []byte) C.DBSlice {
if len(b) == 0 {
return C.DBSlice{data: nil, len: 0}
}
return C.DBSlice{
data: (*C.char)(unsafe.Pointer(&b[0])),
len: C.int(len(b)),
}
}
func goToCKey(key engine.MVCCKey) C.DBKey {
return C.DBKey{
key: goToCSlice(key.Key),
wall_time: C.int64_t(key.Timestamp.WallTime),
logical: C.int32_t(key.Timestamp.Logical),
}
}
func cStringToGoString(s C.DBString) string {
if s.data == nil {
return ""
}
result := C.GoStringN(s.data, s.len)
C.free(unsafe.Pointer(s.data))
return result
}
func statusToError(s C.DBStatus) error {
if s.data == nil {
return nil
}
return errors.New(cStringToGoString(s))
}
func cStatsToGoStats(stats C.MVCCStatsResult, nowNanos int64) (enginepb.MVCCStats, error) {
ms := enginepb.MVCCStats{}
if err := statusToError(stats.status); err != nil {
return ms, err
}
ms.ContainsEstimates = false
ms.LiveBytes = int64(stats.live_bytes)
ms.KeyBytes = int64(stats.key_bytes)
ms.ValBytes = int64(stats.val_bytes)
ms.IntentBytes = int64(stats.intent_bytes)
ms.LiveCount = int64(stats.live_count)
ms.KeyCount = int64(stats.key_count)
ms.ValCount = int64(stats.val_count)
ms.IntentCount = int64(stats.intent_count)
ms.IntentAge = int64(stats.intent_age)
ms.GCBytesAge = int64(stats.gc_bytes_age)
ms.SysBytes = int64(stats.sys_bytes)
ms.SysCount = int64(stats.sys_count)
ms.LastUpdateNanos = nowNanos
return ms, nil
}