ovn-org / libovsdb Goto Github PK
View Code? Open in Web Editor NEWAn OVSDB Client Library written in Golang
License: Apache License 2.0
An OVSDB Client Library written in Golang
License: Apache License 2.0
The following code will return empty result and err "Validation failed for the operation". Looks like the client does not like "_uuid" in the transaction
operation := libovsdb.Operation{
Op: "select",
Table: tableName,
Where: []interface{}{condition},
Columns: {"_uuid"},
}
result, err := db.client.Transact("OpenSwitch", operation)
In the context of remote calls (Update(), Delete(), Mutate()) we currently 2 have ways of building Conditions:
The idea is to have another explicit condition that builds a ovsdb condition object (similarly to what we do for mutations):
The API could look like:
API.Where(API.ExplicitCondition(&obj, []Condition{
{
Field: &obj.MyIntegerField,
Operator: ovsd.ConditionGreaterThan,
Value: 35,
}
})).Delete()
It could be integrated into the ConditionFromModel object somehow as well.
Currently strong enum typing is not supported. #147 added type alias (e.g: type Alias = string
) but, as discussed in that PR, that does not really enforce strong typing limitations.
For that to work we would need to to modify the ovsdb.bindings
and mapper
layers to cope with named-types.
Once core functionality is added, apart from nice enum validation, we can change replace the type alias with named-types in the generator and should be transparent to clients
We need to ensure the code we generate works with the API. Need a test for this
Where() uses variadic args to pass a list of Conditions, Mutate() should use the same so that the API is cleaner and more homogeneous
A lot of the names of things stutter.
Like ovsdb.OvsSet
and client.OvsdbClient
We should try and make this nicer to use.
Currently, we only support cache-based listing using client.List()
. Filtering can be performed by using WhereCache()
. However, this makes it mandatory for clients to use Monitor() so the client registers all the DB updates and populates the cache. This has a significant performance (both in terms of memory and cpu) and might not be desired by the user.
We should support RFC7047 Select operation to allow users to inspect the database without having an in-memory copy of it.
My proposal for the API is to leave List() and Get() for cache-based operations and add a new API method called Select
that performs the homonym operation.
Since the client.Get
and client.List
API do most of the same thing.
This ensures we don't accidentally expose something dangerous (e.g client.Cache().Purge()
) to users.
We'd need to ensure that we could still easily write tests without direct cache access though.
Line 161 in 4f9fd11
When a transaction with a "select" operation is used to retrieve data that has complex data, such as a map, the data is not unmarshalled completely. The OVSDB representation needs custom JSON unmarshalling in order to be decoded properly.
My analysis and recommendation:
The OperationResult structure has a Rows field that is defined as:
Rows []map[string]interface{}
Instead, it could be defined as:
Rows []Row
Reusing the Row type definition allows the custom unmarshal code to correctly organize the complex data. However, that alters the structure so that code would have to use ....Rows[n].Fields[field] instead of ....Rows[n][field], possibly breaking existing applications.
Another approach would be to define a new type:
type RowResult map[string]interface{}
Then create an unmarshal function for the RowResult type that does the same kind of work that the unmarshal function for the Row type does. And:
Rows []RowResult
Now any previous code that accessed ....Rows[n][field] still works, and the data is correctly unmarshaled.
It will be nice to have the OVN cluster support optionally with a leader-only option.
If connect with a no-leader-only
option, the client will do a client-side load balance.
Currently List() respects the capacity of the given list and does not resize it. This is intended so that a client that preallocates a list for optimization purposes is not returned an increased slice.
However, the side efect is that a zero capacity ([]MyRouter{}
) slice does not get populated.
We should consider a slice with capacity==0 in the same way as an nil slice
From the conversation in:
https://github.com/ovn-org/libovsdb/pull/116/files#r644035109
Access TableSchema.Columns with a getter function, e.g:
for name := range append(table.Columns(), "_uuid") {
column := table.Column(name)
}
Dealing with OperationResults is a little tedious.
We should add some helper functions.
E.g:
func (or *operationResults) Errors() []err
, which would return all errors from an operation.
It would also be nice to return a typed error e.g ErrConstraintViolated
which contains details for each one, so a user could do something like:
res, err := client.Transact(ops...)
if err != nil {
// handle connection error
}
if len(res.Errors()) != 0 {
for _, err := res.Errors() {
if err == ErrSomethingSafeToIgnore {
continue
} else {
panic(err)
}
}
}
We have some documentation, but it's not extensive.
We should ensure that:
doc.go
doc_test.go
file see. This ensures that they compile and won't be forgotten with API changesAs #158 adds a model-based monitoring API we can actually remove MonitorAll
.
It would be equivalent to Monitor
with no TableMonitor
options provided.
If the user has not enabled Monitoring (client.MonitorAll
), the cache is empty.
Predicate conditions (API.ConditionFromFunc()
) as well as List() and Get() depend on the cache to work.
For predicate conditions, I'm not arguing we should have them work on cache-less clients but to figure out a good way to report this situation to the user (currently they just return ErrNotFound).
For Get() and List() we could consider generating a select operation
The library does not provide an api to send a "monitor_cancel" JSON-RPC request
According to the RFC 7047 :
4.1.7. Monitor Cancellation
The "monitor_cancel" request cancels a previously issued monitor
request. The request object members are:
"method": "monitor_cancel"
"params": []
"id":
The in "params" matches the in "params" for
the ongoing "monitor" request that is to be canceled. No more
"update" messages will be sent for this table monitor. The response
to this request has the following members:
"result": {}
"error": null
"id": the request "id" member
In the event that a monitor cancellation request refers to an unknown
monitor request, an error response with the following members is
returned:
"result": null
"error": "unknown monitor"
"id": the request "id" member
If we ever wanted another package (e.g server
) to use the ORM layer, this would need to be moved outside the client
package.
How about to add some function to unregister a NotificationHandler from ovs.handlers?
It's used a lot as a return type (e.g client.Create
return []ovsdb.Operation
and as a parameter in client.Transact
Since there are a number of optional fields, constructing operations yourself can be error prone (and annoying when having to create temporary variables to assign to a *string
as literals can't be indirected). To avoid leaking this datastructure outside the OVSDB package, we should consider providing an intermediate type in the client package - like we've done for Condition or Mutation for example:
package client
type Operation interface {
json.Marshaler
json.Unmarshaler
}
We'd also want functions to create new Operations, e.g NewInsertOperation
, NewDeleteOperation
, NewCommentOperation
We need extensive documentation and examples
This was done in #116 for the server side, but API.Get() could also use this.
I'm seing the following error when using libovsdb against the latest OVN Southbound schema
panic: table RBAC_Role, column permissions: failed to extract native element: Wrong Type (OvsToNativeAtomic): expected UUID but got [uuid f7ebfbff-11d3-427a-89c2-a0fab4e0ba88] ([]interface {})
goroutine 1 [running]:
github.com/ovn-org/libovsdb/cache.(*TableCache).Populate(0xc00080e040, 0xc0001ba0c0)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/cache/cache.go:436 +0x725
github.com/ovn-org/libovsdb/client.OvsdbClient.Monitor(0xc0001af260, 0xc000126630, 0xc00020c350, 0xe, 0xc00020c360, 0x7, 0xc000210300, 0xc000804120, 0x1, 0x1, ...)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/client/client.go:339 +0x493
github.com/ovn-org/libovsdb/client.OvsdbClient.MonitorAll(0xc0001af260, 0xc000126630, 0xc00020c350, 0xe, 0xc00020c360, 0x7, 0xc000210300, 0xc000804120, 0x1, 0x1, ...)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/client/client.go:264 +0x274
main.(*OvnShell).Run(0xc000145c80, 0xc000146400, 0xc000116170, 0x0, 0x0)
/home/amorenoz/code/skydive/ovnmodel/cmd/ovnmon/shell.go:122 +0xff
main.main()
/home/amorenoz/code/skydive/ovnmodel/cmd/ovnmon/ovnmon.go:57 +0x398
I occasionally observe the following panic in my test environment.
+++++++++
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x520fa4]
goroutine 74 [running]:
github.com/mapuri/libovsdb.update(0xc20802e840, 0xc2080c9940, 0x2, 0x4, 0xc2080f6800, 0x0, 0x0)
/var/lib/jenkins/jobs/NetpluginPullRequestSanity/workspace/src/github.com/mapuri/libovsdb/client.go:130 +0x564
reflect.Value.call(0x723400, 0x877570, 0x13, 0x7bdd30, 0x4, 0xc20813bf78, 0x3, 0x3, 0x0, 0x0, ...)
/usr/local/go/src/reflect/value.go:419 +0x10e5
reflect.Value.Call(0x723400, 0x877570, 0x13, 0xc20813bf78, 0x3, 0x3, 0x0, 0x0, 0x0)
/usr/local/go/src/reflect/value.go:296 +0xbc
github.com/socketplane/libovsdb/Godeps/_workspace/src/github.com/cenkalti/rpc2.func·001(0x0, 0xc208109900, 0x6)
/var/lib/jenkins/jobs/NetpluginPullRequestSanity/workspace/src/github.com/socketplane/libovsdb/Godeps/_workspace/src/github.com/cenkalti/rpc2/client.go:150 +0x1ad
created by github.com/socketplane/libovsdb/Godeps/_workspace/src/github.com/cenkalti/rpc2.(*Client).readRequest
/var/lib/jenkins/jobs/NetpluginPullRequestSanity/workspace/src/github.com/socketplane/libovsdb/Godeps/_workspace/src/github.com/cenkalti/rpc2/client.go:168 +0x5bc
++++++++++
My environment involves multiple go tests, where each test roughly does the following (I have intentionally removed error handling; logic etc for simplicity) :
func SomeTest(t *testing.T) {
client, err := libovsdb.Connect();
defer func() {
if client {
client.Disconnect()
}
}
//registers some notification handlers
client.Register(myNotifier);
...
//perform some ovs operations
...
}
Based on my understanding of the libovsdb client code I have a potential root-cause, as follows:
In clearConnection() it appears that we set the value pointed by the connection to be nil. I think this leaves a room for a timing window where a go routine (handling ovs notifications over rpc client) might still have some outstanding notifications, while the main go routine (where Disconnect() was called) would have set the value pointed by this key as nil resulting in occasional invalid memory access.
I believe, once a client has called Disconnect() or we receive a disconnect from underlying rpc client, then not keeping the rpc client around shall be okay. So as a fix, I am wondering if deleting the key instead as shown below will help? I have tried it locally and the issues seems to have disappeared for me. Please let me know if this seems like a reasonable fix and I will be happy create a PR.
diff --git a/client.go b/client.go
index 52907a1..6418bdc 100644
--- a/client.go
+++ b/client.go
@@ -231,7 +231,7 @@ func getTableUpdatesFromRawUnmarshal(raw map[string]map[string]RowUpdate) TableU
}
func clearConnection(c *rpc2.Client) {
- connections[c] = nil
+ delete(connections, c)
}
Depends on #116
We should look at using OvsToNative
instead. This wasn't done in the original PR as I couldn't figure out how to get the ColumnSchema to be available when marshalling to a struct from JSON.
The alternative to point_up was to indirect access to the value using Value(schema *ColumnSchema) which would convert it, but I disregarded that but because you could use the wrong ColumnSchema AND you had to use NewCondition/Mutation directly and couldn't quickly create instances of the struct.
The other big issue with OvsToNative apart from needing the ColumnSchema was that it assumes sensible types, and doesn't support the "interesting" types we get from the back from the JSON Parser. E.g []interface{}{"set", []interface{}{[]interface{}{"named-uuid", "foo"}, []interface{}{"named-uuid", "bar"}}}
For example:
ExternalIds
should be ExternalIDs
Acls
should be ACLs
It is much more fluent to be able to call client.Get()
instead of client.API.Get()
The UpdateNotification handling is slow. Looking at pprof I believe this is down to having to marshal/unmarshal to convert the map[string]interface
we get from the RPC library to the type we expect from OVSDB.
We should look at:
rpc2
to allow methods to have any json serialisable structures as parameters. The deser would be handled only once at this layerrpc2
to pass raw bytes instead of interface{}
and have the client-side do the handlingWe may also want to look at the possibility of replacing the current rpc library with somethng else (or building our own).
For example, if I wanted to do and integration test of the client
, I could use a real ovsdb-server
but this would mean packaging one, running one and tearing it down as part of my test. It would only work if I had called Monitor
or MonitorAll
and were making assertions based on what was in the client.Cache
.
Having a server implementation that operates similarly to ovsdb-server
would allow me to:
Tests added in eBay#33 are failing every couple of runs both locally and in CI
=== RUN TestMarshalMap
encoding_test.go:172:
Error Trace: encoding_test.go:172
Error: Not equal:
expected: []interface {}{"map", []interface {}{[]interface {}{"v0", "k0"}, []interface {}{"v1", "k1"}}}
actual : []interface {}{"map", []interface {}{[]interface {}{"v1", "k1"}, []interface {}{"v0", "k0"}}}
Diff:
--- Expected
+++ Actual
@@ -4,8 +4,8 @@
([]interface {}) (len=2) {
+ (string) (len=2) "v1",
+ (string) (len=2) "k1"
+ },
+ ([]interface {}) (len=2) {
(string) (len=2) "v0",
(string) (len=2) "k0"
- },
- ([]interface {}) (len=2) {
- (string) (len=2) "v1",
- (string) (len=2) "k1"
}
Test: TestMarshalMap
Messages: they should be equal
As you can see from the output, the result is somewhat equal 😉 but the order is not the same.
This is likely because Go doesn't guarantee any order when iterating over map keys, which we do in the MarshalJSON function of the OvsMap
type.
We should either:
a) Disable the test
b) Fix the function to test for equality in a better manner
It makes sense that if we generate from a schema, we should also be able to get that Schema too using a DBSchema() *ovsdb.DatabaseSchema
method. This may simplify the library usage a little as we can get the schema from the DBModel
As proposed in #78
This API provides a streamlined and generic way to interface with any OVSDB schema.
A user simply creates structs (which can be auto-generated from a copy of the schema using a tool that will live in this repo), and operations become as easy as:
client.Get
client.List
client.Create
client.Update
client.Mutate
client.Delete
As OVSDB has no Get and List operations, we have to establish a Monitor to replicate the tables in OVSDB in to a cache.
It would be nice if stress
were able to plot the time between when Transact
was called and when the result of the Transaction
was processed by the monitor. Bonus points for tracking the cache propagation time (monitor received to entry in cache)
As mentioned in #84 and implemented in #75
As OVSDB has no Get and List operations, we have to establish a Monitor to replicate the tables in OVSDB in to a cache.
I therefore propose that we add a cache to the Client
by default as well as a UpdateNotifcation
handler that populates the cache from a Monitor
or MonitorAll
.
Most usage of libovsdb
has the client do a Connect
, set up their handler functions and then call MonitorAll
or Monitor
.
This makes sense given the information quoted above.
After this PR, a user can simply call Connect
then Monitor
and they can then interact directly with the cache using a simple API. For example: cache.Table("table_name").Row("named-uuid")
.
If you do not call Monitor
the cache may not be used.
One nice side-effect of the cache is that we can process lifecycle events (add/update/delete) outside of the critical path - i.e we're not stopping the next RPC message from being processed. As such, I recommend that we retire the Register/Unregister
API and use the cache.AddEventHandler
API instead.
The RFC supports adding multiple rows at once (on a single Operation). But the API accepts a single element. We could extend it to accept a slice of Models or have different function to do such thing.
Not sure how relevant the usecase is though.
This fails since #132 was merged as the binaries and generated files have root:root
owners and therefore a subsequent make local
will fail. It would probably be better to retire make test
completely.
Also because we lint
before the files are generated
Remove the -local
version of targets and make them the canonical ones.
And then ensure that we have a local ovs ready to rock and roll in the integration tests using docker-compose up -d ovs
and docker-compose down
afterwards.
Hello,
It appeals client.go::MonitorAll didn't work. It only calls ovs.Monitor only.
Also the Monitor API is not working.
I am using a pica8 ("1.1.1.4") below switch changing link_state value and run "make test"
func TestMonitor(t *testing.T) {
if testing.Short() {
t.Skip()
}
ovs, err := Connect("1.1.1.4", int(6640))
if err != nil {
log.Fatal("Failed to Connect. error:", err)
panic(err)
}
reply, err := ovs.MonitorAll("Open_vSwitch", nil)
if reply == nil || err != nil {
t.Error("Monitor operation failed with reply=", reply, " and error=", err)
} else {
fmt.Println("MonitorAll=",reply)
}
ovs.Disconnect()
}
The test result:
lab203:~/libovsdb-develop$ make test
go test -covermode=count -coverprofile=coverage.out -v
=== RUN TestOpRowSerialization
--- PASS: TestOpRowSerialization (0.00s)
=== RUN TestOpRowsSerialization
--- PASS: TestOpRowsSerialization (0.00s)
=== RUN TestValidateOvsSet
--- PASS: TestValidateOvsSet (0.00s)
=== RUN TestValidateOvsMap
--- PASS: TestValidateOvsMap (0.00s)
=== RUN TestValidateUuid
--- PASS: TestValidateUuid (0.00s)
=== RUN TestNewUUID
--- PASS: TestNewUUID (0.00s)
=== RUN TestNewNamedUUID
--- PASS: TestNewNamedUUID (0.00s)
=== RUN TestNewCondition
--- PASS: TestNewCondition (0.00s)
=== RUN TestNewMutation
--- PASS: TestNewMutation (0.00s)
=== RUN TestConnect
2015/04/16 14:22:39 Couldnt establish OVSDB connection with Defult params. No big deal
2015/04/16 14:22:39 Succ connected OVSDB on 1.1.1.4
--- PASS: TestConnect (0.01s)
=== RUN TestListDbs
db name= [Open_vSwitch]
--- PASS: TestListDbs (0.01s)
=== RUN TestGetSchemas
db schema= Open_vSwitch
--- PASS: TestGetSchemas (0.02s)
=== RUN TestInsertTransact
Bridge Addition Successful : f3a68e6e-325c-4f54-a4b2-f9221a61a1b1
bridgeUuid= f3a68e6e-325c-4f54-a4b2-f9221a61a1b1
--- PASS: TestInsertTransact (0.02s)
=== RUN TestDeleteTransact
Bridge Delete Successful 1
--- PASS: TestDeleteTransact (0.02s)
=== RUN TestMonitor
======================db,cont,request======================= Open_vSwitch map[SSL:{[bootstrap_ca_cert external_ids private_key certificate ca_cert] {true true true true}} Controller:{[local_netmask controller_rate_limit inactivity_probe is_connected role max_backoff target local_ip enable_async_messages controller_burst_limit other_config connection_mode local_gateway external_ids status] {true true true true}} Wred_Queue:{[drop_probability max_thresh min_thresh enable] {true true true true}} Pica8:{[cos_map_enable combinate_actions_enable lag_advance_hash_mapping_fields l3_ecmp_max_ports l3_mode_enable match_mode xovs_ports l3_mode_table l2_mode_enable proxy_arp_subnet l2_l3_preference l2gre_key_length port_mode xovs_vlans l2_mode_table egress_mode_enable] {true true true true}} QoS:{[external_ids other_config queues type] {true true true true}} sFlow:{[external_ids agent targets polling sampling header] {true true true true}} Mirror:{[output_vlan statistics name select_src_port output_port select_vlan select_dst_port select_all external_ids] {true true true true}} Pica_match_mode:{[priority_low options priority_high name] {true true true true}} Flow_Table:{[groups name flow_limit prefixes overflow_policy] {true true true true}} Port:{[status bond_updelay external_ids tag mac fake_bridge bond_downdelay other_config interfaces lacp bond_fake_iface qos statistics name bond_mode trunks vlan_mode] {true true true true}} Flow_Sample_Collector_Set:{[external_ids bridge id ipfix] {true true true true}} IPFIX:{[cache_max_flows external_ids cache_active_timeout targets obs_domain_id sampling obs_point_id] {true true true true}} Open_vSwitch:{[next_cfg system_version manager_options bridges ssl system_type external_ids statistics ovs_version db_version pica8 cur_cfg other_config] {true true true true}} Interface:{[statistics name link_resets ifindex ingress_policing_rate cfm_fault_status ofport external_ids mtu duplex cfm_mpid cfm_fault cfm_remote_mpids other_config lldp_admin_status ofport_request wred_queues bfd_status admin_state cfm_health mac_in_use bfd link_state lacp_current cfm_flap_count status mac ingress_policing_burst cfm_remote_opstate options type lldp_neighbors link_speed] {true true true true}} NetFlow:{[add_id_to_interface engine_id active_timeout targets engine_type external_ids] {true true true true}} LLDP_Neighbor:{[port_description system_description local_id system_name mgmt_address remote_id] {true true true true}} Manager:{[external_ids status other_config inactivity_probe connection_mode max_backoff is_connected target] {true true true true}} Bridge:{[fail_mode lldp_enable controller flood_vlans sflow datapath_id protocols name external_ids status ipfix ports mirrors datapath_type flow_tables stp_enable other_config netflow] {true true true true}} Queue:{[dscp external_ids other_config] {true true true true}}]
The tool in examples/stress
is a good start to understanding what bottlenecks, if any, exist in the code.
To reproduce:
docker-compose up -d ovs
# grab ovsdb port number
docker ps
go run ./example/stress/stress.go -cpuprofile prof.out -ovsdb tcp::49163 -ninserts 1000
go tool pprof -http=":8081" prof.out
Here is a sample of 1000 insert operations:
For bridge creation, things look reasonable:
0.11s was spent on encoding requests and interestingly 0.4s of that was on UUID encoding - validateUUID
.
The majority of the program was spent on the libovsdb.update
function, which consumes OVSDB update notifications before dispatching them to handlers
What's curious here is that we cast the <table_update>
parameter to a map[string]interface{}
, then json.Marshal
it to []byte
.
Then we json.Unmarshal
the []byte
in to a map[string]map[string]RowUpdate
. Maybe there is room for improvement here.
I propose the following:
-bench
flag to go test
in CI so we can actually validate that a fix does indeed provide a measurable improvement.After #166 has merged we should consider supporting multiple monitors and potentially resuming them on reconnect.
If we could resume on reconnect, then we could quite possibly add an option WithReconnect
to reduce the amount of user code to deal with handling disconnects. We'd need to consider whether there would be a Deadline for reconnect before we return an error back to the client, and what that might look like WithReconnet(timeout time.Duration, err chan error)
?
Implementation-wise we'd need to think about the following:
jsonContext
for each Monitor is uniquefunc (o *ovsdbClient) Monitor(...) (uuid, error)
so it can be used for MonitorCancel
Monitor
with options in a map on the ovsdbClient
- this will be needed for update()
to know which monitor request an update is for. It may also be useful to re-establish monitors after the client has been disconnectedOvsToNative will error if it encounters a pointer to one of the composite types.
The object in question came from mapper.NewRow
We should either adjust NewRow
to produce something that OvsToNative
can understand, or we should amend OvsToNative
to handle pointers.
I'm really keen on adding support for opentelemetry.io
This would require:
ctx context.Context
to all clientAPI calls, which seems sensible for multiple reasons (i.e timeouts)Now due to the inconsistency between Godoc and Github, it is hard to automate model installation via go mod.
So please ensure Godoc is up to date with the latest API version.
When we encounter an enum or a set of enums we should generate something like:
type BridgeProtocols string
const (
BridgeProtocolsOpenFlow10 BridgeProtocols = "OpenFlow10"
BridgeProtocolsOpenFlow10 BridgeProtocols = "OpenFlow10"
BridgeProtocolsOpenFlow10 BridgeProtocols = "OpenFlow10"
BridgeProtocolsOpenFlow10 BridgeProtocols = "OpenFlow10"
BridgeProtocolsOpenFlow10 BridgeProtocols = "OpenFlow10"
BridgeProtocolsOpenFlow10 BridgeProtocols = "OpenFlow10"
)
type Bridge struct {
Protocols []Protocols
}
panic: column datapath,tunnel_key not found in orm info
goroutine 19 [running]:
github.com/ovn-org/libovsdb/cache.(*TableCache).Populate(0xc00019a640, 0xc00063c510)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/cache/cache.go:458 +0x651
github.com/ovn-org/libovsdb/cache.(*TableCache).Update(0xc00019a640, 0x6d2360, 0x95e300, 0xc00063c510)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/cache/cache.go:388 +0x4c
github.com/ovn-org/libovsdb/client.(*OvsdbClient).update(0xc0000d6400, 0xc000078600, 0x2, 0x4, 0xc000634438, 0x0, 0x0)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/client/client.go:211 +0x212
github.com/ovn-org/libovsdb/client.newRPC2Client.func2(0xc00013f2d0, 0xc000078600, 0x2, 0x4, 0xc000634438, 0x0, 0x0)
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/client/client.go:98 +0x52
reflect.Value.call(0x6df240, 0xc0001420a0, 0x13, 0x73826a, 0x4, 0xc000131d78, 0x3, 0x3, 0xc000131cc0, 0x4bbd0b, ...)
/usr/lib/golang/src/reflect/value.go:476 +0x8e7
reflect.Value.Call(0x6df240, 0xc0001420a0, 0x13, 0xc000131d78, 0x3, 0x3, 0xc000634408, 0xc000131d50, 0x4ee21a)
/usr/lib/golang/src/reflect/value.go:337 +0xb9
github.com/cenkalti/rpc2.(*Client).handleRequest(0xc00013f2d0, 0x0, 0xc0006244f0, 0x6, 0xc0000d5d00, 0x6cd7c0, 0xc000634408, 0x197)
/home/amorenoz/code/go/pkg/mod/github.com/cenkalti/[email protected]/client.go:134 +0x1cf
github.com/cenkalti/rpc2.(*Client).readRequest(0xc00013f2d0, 0xc00000e018, 0xc00000e030, 0x0)
/home/amorenoz/code/go/pkg/mod/github.com/cenkalti/[email protected]/client.go:184 +0x1cb
github.com/cenkalti/rpc2.(*Client).readLoop(0xc00013f2d0)
/home/amorenoz/code/go/pkg/mod/github.com/cenkalti/[email protected]/client.go:93 +0x165
github.com/cenkalti/rpc2.(*Client).Run(0xc00013f2d0)
/home/amorenoz/code/go/pkg/mod/github.com/cenkalti/[email protected]/client.go:62 +0x2b
created by github.com/ovn-org/libovsdb/client.newRPC2Client
/home/amorenoz/code/go/src/github.com/ovn-org/libovsdb/client/client.go:100 +0x491
Hi. Can you share me info, why this package depend on rpc2?
All APIs should return []Operation, This makes it easier when dealing with batching operations in to a single transaction
Add an -nclients
option to cmd/stress
this will have each client generate N operations.
This will allow for testing performance of a server when multiple clients are monitoring.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.