-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple_api.go
145 lines (138 loc) · 5.54 KB
/
simple_api.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
//////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2018-2022 YottaDB LLC and/or its subsidiaries. //
// All rights reserved. //
// //
// This source code contains the intellectual property //
// of its copyright holder(s), and is made available //
// under a license. If you do not know the terms of //
// the license, please stop and do not read further. //
// //
//////////////////////////////////////////////////////////////////
package yottadb
import (
"fmt"
"runtime"
"strings"
"sync/atomic"
"unsafe"
)
// #include "libyottadb.h"
// /* C routine to get around the cgo issue and its lack of support for variadic plist routines */
// void *ydb_get_lockst_funcvp(void);
// void *ydb_get_lockst_funcvp(void)
// {
// return (void *)&ydb_lock_st;
// }
import "C"
//
// This file contains the only Simple API routine that is not a method. The rest of the threaded SimpleAPI method functions
// are defined in buffer_t.go, bufer_t_array.go, and key_t.go with utilities being defined in util.go.
//
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Simple (Threaded) API function(s)
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// LockST is a STAPI function that releases all existing locks then locks the supplied variadic list of lock keys.
func LockST(tptoken uint64, errstr *BufferT, timeoutNsec uint64, lockname ...*KeyT) error {
var vplist variadicPlist
var lockcnt, namecnt int
var parmIndx uint32
var err error
var cbuft *C.ydb_buffer_t
printEntry("KeyT.SubNextST()")
if 1 != atomic.LoadUint32(&ydbInitialized) {
initializeYottaDB()
}
defer vplist.free()
vplist.alloc()
// First two parms are the tptoken and the contents of the errstr BufferT (not the BufferT itself).
err = vplist.setVPlistParam64Bit(tptoken, errstr, &parmIndx, tptoken) // Takes care of bumping parmIndx
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam64Bit(): %s", err))
}
if nil != errstr {
cbuft = errstr.getCPtr()
}
err = vplist.setVPlistParam(tptoken, errstr, parmIndx, uintptr(unsafe.Pointer(cbuft)))
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam(): %s", err))
}
parmIndx++
// Put the timeout parameter into the plist
err = vplist.setVPlistParam64Bit(tptoken, errstr, &parmIndx, timeoutNsec) // Takes care of bumping parmIndx
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam(): %s", err))
}
// Add the lock count parameter
lockcnt = len(lockname)
namecnt = lockcnt
err = vplist.setVPlistParam(tptoken, errstr, parmIndx, uintptr(namecnt))
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam(): %s", err))
}
parmIndx++
if 0 != lockcnt {
parmsleft := C.MAX_GPARAM_LIST_ARGS - parmIndx // We've already slotted 4 parms in up to 6 slots
parmsleftorig := parmsleft // Save for error below just-in-case
lockindx := 0 // The next lockname index to be read
// Load the lockname parameters into the plist
for 0 < lockcnt {
// Make sure enough room for another set of 3 parms
if 3 > parmsleft {
errmsg, err := MessageT(tptoken, nil, (int)(YDB_ERR_NAMECOUNT2HI))
if nil != err {
panic(fmt.Sprintf("YDB: Error fetching NAMECOUNT2HI: %s", err))
}
// Do some error message substitution
errmsg = strings.Replace(errmsg, "!AD", "LockST()", 1)
errmsg = strings.Replace(errmsg, "!UL", fmt.Sprintf("%d", namecnt), 1)
errmsg = strings.Replace(errmsg, "!UL", fmt.Sprintf("%d", parmsleftorig/3), 1)
return &YDBError{(int)(YDB_ERR_NAMECOUNT2HI), errmsg}
}
// Set the 3 parameters for this lockname
err = vplist.setVPlistParam(tptoken, errstr,
parmIndx, uintptr(unsafe.Pointer(lockname[lockindx].Varnm.getCPtr())))
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam(): %s", err))
}
parmIndx++
parmsleft--
err = vplist.setVPlistParam(tptoken, errstr, parmIndx, uintptr(lockname[lockindx].Subary.ElemUsed()))
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam(): %s", err))
}
parmIndx++
parmsleft--
subgobuftary := lockname[lockindx].Subary
subbuftary := unsafe.Pointer(subgobuftary.getCPtr())
err = vplist.setVPlistParam(tptoken, errstr, parmIndx, uintptr(subbuftary))
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setVPlistParam(): %s", err))
}
parmIndx++
parmsleft--
// Housekeeping
lockindx++
lockcnt--
}
}
err = vplist.setUsed(tptoken, errstr, parmIndx)
if nil != err {
panic(fmt.Sprintf("YDB: Unknown error with varidicPlist.setUsed(): %s", err))
}
// At this point, vplist now contains the plist we want to send to ydb_lock_s(). However, Go/cgo does not permit
// either the call or even creating a function pointer to ydb_lock_s(). So instead of driving vplist.CallVariadicPlistFuncST()
// which is what we would normally do here, we're going to call a C helper function (defined in the cgo preamble at the
// top of this routine) to do the call that callVariadicPlistFuncST() would have done.
rc := vplist.callVariadicPlistFunc(C.ydb_get_lockst_funcvp()) // Drive ydb_lock_st()
if YDB_OK != rc {
err := NewError(tptoken, errstr, int(rc))
return err
}
runtime.KeepAlive(lockname) // Make sure these structures hangs around through the YDB call
runtime.KeepAlive(errstr)
runtime.KeepAlive(vplist)
return nil
}