ovirt-engine-sdk 4.2.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bf11e3460b2e00a5fd673a768a84b1e22657fec7
4
- data.tar.gz: '028c4fd704c4591c5753de18f2dbbfdecbeac1e1'
3
+ metadata.gz: 573f19600decb51717ca7b46538158f0bfe145c9
4
+ data.tar.gz: a42480a7c2627d263106163ecd835c80f0ef2b53
5
5
  SHA512:
6
- metadata.gz: cc8b6ac930ddb084da2dcd0e8164044939c8601e81e8d432495e0b3673401ecd583c77da9240498c4329a7085d41e1caa984585ae3da33a6d7086ee3acf6770d
7
- data.tar.gz: 739766ec3dd856e92d9829c44a321109b6e5568097a98fb6a739ba435c293e8c6c85bf08fefb7b32df8da19dd1c4f8b889657fe29bff9a548648fae0414c07c8
6
+ metadata.gz: 3a8a06fe3746bf4c82c9d18c5d9dce0920f6202857444e830c4e917e2d8bacfc2ac9bdd802402a9049b7df029105837c41f1c0c94e3cd7ffc50750abefd66547
7
+ data.tar.gz: 97c010a0aee2fa5e496df698790a65be800522c4271db84aba09cf3fe6be1794aec263a0f7607edc22eb8aa48fda629a018e182d9e1d872c716b68626deb1219
@@ -2,6 +2,16 @@
2
2
 
3
3
  This document describes the relevant changes between releases of the SDK.
4
4
 
5
+ == 4.2.1 / Dec 13 2017
6
+
7
+ Bug fixes:
8
+
9
+ * Fix handling of the `all_content` parameter
10
+ https://bugzilla.redhat.com/1525555[#1525555].
11
+
12
+ * Limit the number of requests sent to `libcurl`
13
+ https://bugzilla.redhat.com/1525302[#1525302].
14
+
5
15
  == 4.2.0 / Dec 4 2017
6
16
 
7
17
  No chages, version `4.2.0` is identical to `4.2.0-beta2`, only the
@@ -64,16 +64,21 @@ static ID READ_ID;
64
64
  static ID STRING_ID;
65
65
  static ID STRING_IO_ID;
66
66
  static ID URI_ID;
67
+ static ID WARN_ID;
68
+ static ID WARN_Q_ID;
67
69
  static ID WRITE_ID;
68
70
 
69
71
  /* References to classes: */
70
- static VALUE URI_CLASS;
71
72
  static VALUE STRING_IO_CLASS;
73
+ static VALUE URI_CLASS;
72
74
 
73
75
  /* Constants: */
74
76
  const char CR = '\x0D';
75
77
  const char LF = '\x0A';
76
78
 
79
+ /* Version of libcurl: */
80
+ static curl_version_info_data* libcurl_version;
81
+
77
82
  /* Before version 7.38.0 of libcurl the NEGOTIATE authentication method was named GSSNEGOTIATE: */
78
83
  #ifndef CURLAUTH_NEGOTIATE
79
84
  #define CURLAUTH_NEGOTIATE CURLAUTH_GSSNEGOTIATE
@@ -85,6 +90,21 @@ const char LF = '\x0A';
85
90
  #define CURLPIPE_HTTP1 1
86
91
  #endif
87
92
 
93
+ /* Define options that may not be available in some versions of libcurl: */
94
+ #if LIBCURL_VERSION_NUM < 0x071e00 /* 7.30.0 */
95
+ #define CURLMOPT_MAX_HOST_CONNECTIONS 7
96
+ #define CURLMOPT_MAX_PIPELINE_LENGTH 8
97
+ #define CURLMOPT_MAX_TOTAL_CONNECTIONS 13
98
+ #endif
99
+
100
+ #if LIBCURL_VERSION_NUM < 0x070f03 /* 7.16.3 */
101
+ #define CURLMOPT_MAXCONNECTS 6
102
+ #endif
103
+
104
+ #if LIBCURL_VERSION_NUM < 0x070f00 /* 7.16.0 */
105
+ #define CURLMOPT_PIPELINING 3
106
+ #endif
107
+
88
108
  typedef struct {
89
109
  VALUE io; /* IO */
90
110
  char* ptr;
@@ -131,6 +151,22 @@ static void ov_http_client_log_info(VALUE log, const char* format, ...) {
131
151
  }
132
152
  }
133
153
 
154
+ static void ov_http_client_log_warn(VALUE log, const char* format, ...) {
155
+ VALUE enabled;
156
+ VALUE message;
157
+ va_list args;
158
+
159
+ if (!NIL_P(log)) {
160
+ enabled = rb_funcall(log, WARN_Q_ID, 0);
161
+ if (RTEST(enabled)) {
162
+ va_start(args, format);
163
+ message = rb_vsprintf(format, args);
164
+ rb_funcall(log, WARN_ID, 1, message);
165
+ va_end(args);
166
+ }
167
+ }
168
+ }
169
+
134
170
  static void ov_http_client_check_closed(ov_http_client_object* object) {
135
171
  if (object->handle == NULL) {
136
172
  rb_raise(ov_error_class, "The client is already closed");
@@ -142,6 +178,7 @@ static void ov_http_client_mark(void* vptr) {
142
178
 
143
179
  ptr = vptr;
144
180
  rb_gc_mark(ptr->log);
181
+ rb_gc_mark(ptr->queue);
145
182
  rb_gc_mark(ptr->pending);
146
183
  rb_gc_mark(ptr->completed);
147
184
  }
@@ -192,6 +229,8 @@ static VALUE ov_http_client_alloc(VALUE klass) {
192
229
  ptr->handle = NULL;
193
230
  ptr->share = NULL;
194
231
  ptr->log = Qnil;
232
+ ptr->limit = 0;
233
+ ptr->queue = Qnil;
195
234
  ptr->pending = Qnil;
196
235
  ptr->completed = Qnil;
197
236
  ptr->compress = false;
@@ -567,16 +606,22 @@ static VALUE ov_http_client_initialize(int argc, VALUE* argv, VALUE self) {
567
606
  Check_Type(opt, T_FIXNUM);
568
607
  pipeline = NUM2LONG(opt);
569
608
  }
609
+ if (pipeline < 0) {
610
+ rb_raise(rb_eArgError, "The maximum pipeline length can't be %ld, minimum is 0.", pipeline);
611
+ }
570
612
 
571
613
  /* Get the value of the 'connections' parameter: */
572
614
  opt = rb_hash_aref(opts, CONNECTIONS_SYMBOL);
573
615
  if (NIL_P(opt)) {
574
- connections = 0;
616
+ connections = 1;
575
617
  }
576
618
  else {
577
619
  Check_Type(opt, T_FIXNUM);
578
620
  connections = NUM2LONG(opt);
579
621
  }
622
+ if (connections < 1) {
623
+ rb_raise(rb_eArgError, "The maximum number of connections can't be %ld, minimum is 1.", connections);
624
+ }
580
625
 
581
626
  /* Get the value of the 'cookies' parameter. If it is a string it will be used as the path of the file where the
582
627
  cookies will be stored. If it is any other thing it will be treated as a boolean flag indicating if cookies
@@ -592,11 +637,22 @@ static VALUE ov_http_client_initialize(int argc, VALUE* argv, VALUE self) {
592
637
  ptr->cookies = NULL;
593
638
  }
594
639
 
640
+ /* Create the queue that contains requests that haven't been sent to libcurl yet: */
641
+ ptr->queue = rb_ary_new();
642
+
595
643
  /* Create the hash that contains the transfers are pending an completed. Both use the identity of the request
596
644
  as key. */
597
645
  ptr->completed = rb_funcall(rb_hash_new(), COMPARE_BY_IDENTITY_ID, 0);
598
646
  ptr->pending = rb_funcall(rb_hash_new(), COMPARE_BY_IDENTITY_ID, 0);
599
647
 
648
+ /* Calculate the max number of requests that can be handled by libcurl simultaneously. For versions of libcurl
649
+ newer than 7.30.0 the limit can be increased when using pipelining. For older versions it can't be increased
650
+ because libcurl would create additional connections for the requests that can't be pipelined. */
651
+ ptr->limit = connections;
652
+ if (pipeline > 0 && libcurl_version->version_num >= 0x071e00 /* 7.30.0 */) {
653
+ ptr->limit *= pipeline;
654
+ }
655
+
600
656
  /* Create the libcurl multi handle: */
601
657
  ptr->handle = curl_multi_init();
602
658
  if (ptr->handle == NULL) {
@@ -615,14 +671,47 @@ static VALUE ov_http_client_initialize(int argc, VALUE* argv, VALUE self) {
615
671
  /* Enable pipelining: */
616
672
  if (pipeline > 0) {
617
673
  curl_multi_setopt(ptr->handle, CURLMOPT_PIPELINING, CURLPIPE_HTTP1);
618
- #ifdef CURLMOPT_MAX_PIPELINE_LENGTH
619
- curl_multi_setopt(ptr->handle, CURLMOPT_MAX_PIPELINE_LENGTH, pipeline);
620
- #endif
674
+ if (libcurl_version->version_num >= 0x071e00 /* 7.30.0 */) {
675
+ curl_multi_setopt(ptr->handle, CURLMOPT_MAX_PIPELINE_LENGTH, pipeline);
676
+ }
677
+ else {
678
+ ov_http_client_log_warn(
679
+ ptr->log,
680
+ "Can't set maximum pipeline length to %d, it isn't supported by libcurl %s. Upgrade to 7.30.0 or "
681
+ "newer to avoid this issue.",
682
+ pipeline,
683
+ libcurl_version->version
684
+ );
685
+ }
621
686
  }
687
+
688
+ /* Set the max number of connections: */
622
689
  if (connections > 0) {
623
- #ifdef CURLMOPT_MAX_HOST_CONNECTIONS
624
- curl_multi_setopt(ptr->handle, CURLMOPT_MAX_HOST_CONNECTIONS, connections);
625
- #endif
690
+ if (libcurl_version->version_num >= 0x071e00 /* 7.30.0 */) {
691
+ curl_multi_setopt(ptr->handle, CURLMOPT_MAX_HOST_CONNECTIONS, connections);
692
+ curl_multi_setopt(ptr->handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, connections);
693
+ }
694
+ else {
695
+ ov_http_client_log_warn(
696
+ ptr->log,
697
+ "Can't set maximum number of connections to %d, it isn't supported by libcurl %s. Upgrade to 7.30.0 "
698
+ "or newer to avoid this issue.",
699
+ connections,
700
+ libcurl_version->version
701
+ );
702
+ }
703
+ if (libcurl_version->version_num >= 0x070f03 /* 7.16.3 */) {
704
+ curl_multi_setopt(ptr->handle, CURLMOPT_MAXCONNECTS, connections);
705
+ }
706
+ else {
707
+ ov_http_client_log_warn(
708
+ ptr->log,
709
+ "Can't set total maximum connection cache size to %d, it isn't supported by libcurl %s. Upgrade to "
710
+ "7.16.3 or newer to avoid this issue.",
711
+ connections,
712
+ libcurl_version->version
713
+ );
714
+ }
626
715
  }
627
716
 
628
717
  return self;
@@ -922,7 +1011,7 @@ static void ov_http_client_prepare_handle(ov_http_client_object* client_ptr, ov_
922
1011
  );
923
1012
  }
924
1013
 
925
- static VALUE ov_http_client_send(VALUE self, VALUE request) {
1014
+ static VALUE ov_http_client_submit(VALUE self, VALUE request) {
926
1015
  CURL* handle;
927
1016
  VALUE response;
928
1017
  VALUE transfer;
@@ -992,7 +1081,26 @@ static VALUE ov_http_client_send(VALUE self, VALUE request) {
992
1081
  return Qnil;
993
1082
  }
994
1083
 
1084
+ static VALUE ov_http_client_send(VALUE self, VALUE request) {
1085
+ ov_http_client_object* ptr;
1086
+
1087
+ /* Get the pointer to the native object and check that it isn't closed: */
1088
+ ov_http_client_ptr(self, ptr);
1089
+ ov_http_client_check_closed(ptr);
1090
+
1091
+ /* If the limit hasn't been reached then submit the request directly to libcurl, otherwise put it in the queue: */
1092
+ if (RHASH_SIZE(ptr->pending) < ptr->limit) {
1093
+ ov_http_client_submit(self, request);
1094
+ }
1095
+ else {
1096
+ rb_ary_push(ptr->queue, request);
1097
+ }
1098
+
1099
+ return Qnil;
1100
+ }
1101
+
995
1102
  static VALUE ov_http_client_wait(VALUE self, VALUE request) {
1103
+ VALUE next;
996
1104
  VALUE result;
997
1105
  ov_http_client_object* ptr;
998
1106
  ov_http_client_wait_context context;
@@ -1001,15 +1109,24 @@ static VALUE ov_http_client_wait(VALUE self, VALUE request) {
1001
1109
  ov_http_client_ptr(self, ptr);
1002
1110
  ov_http_client_check_closed(ptr);
1003
1111
 
1004
- /* Work till the transfer has been completed: */
1112
+ /* Work till the transfer has been completed. */
1005
1113
  context.handle = ptr->handle;
1006
1114
  context.code = CURLE_OK;
1007
1115
  context.cancel = false;
1008
1116
  for (;;) {
1117
+ /* Move requests from the queue to libcurl: */
1118
+ while (RARRAY_LEN(ptr->queue) > 0 && RHASH_SIZE(ptr->pending) < ptr->limit) {
1119
+ next = rb_ary_shift(ptr->queue);
1120
+ ov_http_client_submit(self, next);
1121
+ }
1122
+
1123
+ /* Check if the response is already available, if so then return it: */
1009
1124
  result = rb_hash_delete(ptr->completed, request);
1010
1125
  if (!NIL_P(result)) {
1011
1126
  return result;
1012
1127
  }
1128
+
1129
+ /* If the response isn't available yet, then do some real work: */
1013
1130
  rb_thread_call_without_gvl(
1014
1131
  ov_http_client_wait_task,
1015
1132
  &context,
@@ -1082,6 +1199,8 @@ void ov_http_client_define(void) {
1082
1199
  STRING_ID = rb_intern("string");
1083
1200
  STRING_IO_ID = rb_intern("StringIO");
1084
1201
  URI_ID = rb_intern("URI");
1202
+ WARN_ID = rb_intern("warn");
1203
+ WARN_Q_ID = rb_intern("warn?");
1085
1204
  WRITE_ID = rb_intern("write");
1086
1205
 
1087
1206
  /* Locate classes: */
@@ -1093,4 +1212,7 @@ void ov_http_client_define(void) {
1093
1212
  if (code != CURLE_OK) {
1094
1213
  rb_raise(ov_error_class, "Can't initialize libcurl: %s", curl_easy_strerror(code));
1095
1214
  }
1215
+
1216
+ /* Get the libcurl version: */
1217
+ libcurl_version = curl_version_info(CURLVERSION_NOW);
1096
1218
  }
@@ -37,7 +37,14 @@ typedef struct {
37
37
  /* The logger: */
38
38
  VALUE log;
39
39
 
40
- /* This hash store the transfers that are pending. The key of the hash is the request that initiated the transfer,
40
+ /* The max number of requests that can be processed simultaneously by libcurl. Will be calculated multiplying the
41
+ max number of connections by the pipeline length: */
42
+ int limit;
43
+
44
+ /* This queue contains the requests that have not yet been sent to libcurl for processing: */
45
+ VALUE queue;
46
+
47
+ /* This hash stores the transfers that are pending. The key of the hash is the request that initiated the transfer,
41
48
  and the value is the transfer itself. */
42
49
  VALUE pending;
43
50
 
@@ -101,8 +101,8 @@ module OvirtSDK4
101
101
  # as the names of the headers. If the same header is provided here and in the `headers` parameter of a specific
102
102
  # method call, then the `headers` parameter of the specific method call will have precedence.
103
103
  #
104
- # @option opts [Integer] :connections (0) The maximum number of connections to open to the host. If the value is
105
- # `0` (the default) then the number of connections will be unlimited.
104
+ # @option opts [Integer] :connections (1) The maximum number of connections to open to the host. The value must
105
+ # be greater than 0.
106
106
  #
107
107
  # @option opts [Integer] :pipeline (0) The maximum number of request to put in an HTTP pipeline without waiting for
108
108
  # the response. If the value is `0` (the default) then pipelining is disabled.
@@ -126,7 +126,7 @@ module OvirtSDK4
126
126
  @proxy_username = opts[:proxy_username]
127
127
  @proxy_password = opts[:proxy_password]
128
128
  @headers = opts[:headers]
129
- @connections = opts[:connections] || 0
129
+ @connections = opts[:connections] || 1
130
130
  @pipeline = opts[:pipeline] || 0
131
131
 
132
132
  # Check that the URL has been provided:
@@ -275,9 +275,7 @@ module OvirtSDK4
275
275
  def follow_link(object)
276
276
  # Check that the "href" has a value, as it is needed in order to retrieve the representation of the object:
277
277
  href = object.href
278
- if href.nil?
279
- raise Error, "Can't follow link because the 'href' attribute doesn't have a value"
280
- end
278
+ raise Error, "Can't follow link because the 'href' attribute doesn't have a value" if href.nil?
281
279
 
282
280
  # Check that the value of the "href" attribute is compatible with the base URL of the connection:
283
281
  prefix = URI(@url).path
@@ -634,7 +632,7 @@ module OvirtSDK4
634
632
  # parameter. In order to better support those older versions of the engine we need to check if this parameter is
635
633
  # included in the request, and add the corresponding header.
636
634
  unless request.query.nil?
637
- all_content = request.query['all_content']
635
+ all_content = request.query[:all_content]
638
636
  request.headers['All-Content'] = all_content unless all_content.nil?
639
637
  end
640
638
 
@@ -175,7 +175,7 @@ module OvirtSDK4
175
175
  # Get the values of the options specific to this operation:
176
176
  specs.each do |name, kind|
177
177
  value = opts.delete(name)
178
- query[name] = Writer.render(value, kind) if value
178
+ query[name] = Writer.render(value, kind) unless value.nil?
179
179
  end
180
180
 
181
181
  # Check the remaining options:
@@ -224,7 +224,7 @@ module OvirtSDK4
224
224
  # Get the values of the options specific to this operation:
225
225
  specs.each do |name, kind|
226
226
  value = opts.delete(name)
227
- query[name] = Writer.render(value, kind) if value
227
+ query[name] = Writer.render(value, kind) unless value.nil?
228
228
  end
229
229
 
230
230
  # Check the remaining options:
@@ -274,7 +274,7 @@ module OvirtSDK4
274
274
  # Get the values of the options specific to this operation:
275
275
  specs.each do |name, kind|
276
276
  value = opts.delete(name)
277
- query[name] = Writer.render(value, kind) if value
277
+ query[name] = Writer.render(value, kind) unless value.nil?
278
278
  end
279
279
 
280
280
  # Check the remaining options:
@@ -321,7 +321,7 @@ module OvirtSDK4
321
321
  # Get the values of the options specific to this operation:
322
322
  specs.each do |name, kind|
323
323
  value = opts.delete(name)
324
- query[name] = Writer.render(value, kind) if value
324
+ query[name] = Writer.render(value, kind) unless value.nil?
325
325
  end
326
326
 
327
327
  # Check the remaining options:
@@ -407,9 +407,7 @@ module OvirtSDK4
407
407
  def internal_read_body(response)
408
408
  # First check if the response body is empty, as it makes no sense to check the content type if there is
409
409
  # no body:
410
- if response.body.nil? || response.body.length.zero?
411
- connection.raise_error(response, 'The response body is empty')
412
- end
410
+ connection.raise_error(response, 'The response body is empty') if response.body.nil? || response.body.length.zero?
413
411
 
414
412
  # Check the content type, as otherwise the parsing will fail, and the resulting error message won't be explicit
415
413
  # about the cause of the problem:
@@ -16,5 +16,5 @@
16
16
 
17
17
 
18
18
  module OvirtSDK4
19
- VERSION = '4.2.0'.freeze
19
+ VERSION = '4.2.1'.freeze
20
20
  end
@@ -195,9 +195,7 @@ module OvirtSDK4
195
195
  begin
196
196
  if object.is_a?(Array)
197
197
  # For arrays we can't decide which tag to use, so the 'root' parameter is mandatory in this case:
198
- if root.nil?
199
- raise Error, "The 'root' option is mandatory when writing arrays"
200
- end
198
+ raise Error, "The 'root' option is mandatory when writing arrays" if root.nil?
201
199
 
202
200
  # Write the root tag, and then recursively call the method to write each of the items of the array:
203
201
  cursor.write_start(root)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ovirt-engine-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Hernandez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-04 00:00:00.000000000 Z
11
+ date: 2017-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -151,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
151
  requirements:
152
152
  - - ">="
153
153
  - !ruby/object:Gem::Version
154
- version: '2.0'
154
+ version: '2.1'
155
155
  required_rubygems_version: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - ">="