couchbase 1.2.0.z.beta2 → 1.2.0.z.beta3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,18 @@
1
+ ## 1.2.0.z.beta3 / 2012-10-12
2
+
3
+ * Update view API
4
+ * Mention couchbase-model and em-couchbase in README
5
+ * Use global scope to find Error classes (thanks to @wr0ngway)
6
+ * RCBC-87 Fix build error on macos
7
+ * Use lcb_breakout()
8
+ * Propogate status code for HTTP responses
9
+ * Extract params encoding for easier reusage
10
+ * Destory IO operations struct (fix memleak)
11
+ * Don't try to convert error to number, it is exception object
12
+ * Update error codes
13
+ * Implement bucket create/delete operations
14
+ * Fixup FLUSH tests
15
+
1
16
  ## 1.2.0.z.beta2 / 2012-09-19
2
17
 
3
18
  * RCBC-82 Fix extconf.rb for RVM/MacOS. (Not all rubies are fat on MacOS)
@@ -1,6 +1,13 @@
1
- # Couchbase Ruby Client [![Build Status](https://secure.travis-ci.org/couchbase/couchbase-ruby-client.png?branch=master)](http://travis-ci.org/couchbase/couchbase-ruby-client)
1
+ # Couchbase Ruby Client
2
2
 
3
- This is the official client library for use with Couchbase Server.
3
+ This is the official client library for use with Couchbase Server. There
4
+ are related libraries available:
5
+
6
+ * [couchbase-model][6] the ActiveModel implementation, git repository:
7
+ [https://github.com/couchbase/couchbase-ruby-model][7]
8
+
9
+ * [em-couchbase][8] EventMachine friendly implementation of couchbase
10
+ client, git repository: [https://github.com/couchbase/couchbase-ruby-client-em][9]
4
11
 
5
12
  ## SUPPORT
6
13
 
@@ -519,3 +526,8 @@ the error is detected.
519
526
  [3]: http://www.couchbase.com/develop/c/current
520
527
  [4]: https://github.com/mxcl/homebrew/pulls/avsej
521
528
  [5]: http://code.google.com/p/memcached/wiki/BinaryProtocolRevamped
529
+ [6]: https://rubygems.org/gems/couchbase-model
530
+ [7]: https://github.com/couchbase/couchbase-ruby-model
531
+ [8]: https://rubygems.org/gems/em-couchbase
532
+ [9]: https://github.com/couchbase/couchbase-ruby-client-em
533
+
@@ -22,7 +22,7 @@ error_callback(lcb_t handle, lcb_error_t error, const char *errinfo)
22
22
  {
23
23
  struct bucket_st *bucket = (struct bucket_st *)lcb_get_cookie(handle);
24
24
 
25
- bucket->io->stop_event_loop(bucket->io);
25
+ lcb_breakout(handle);
26
26
  bucket->exception = cb_check_error(error, errinfo, Qnil);
27
27
  }
28
28
 
@@ -34,6 +34,7 @@ cb_bucket_free(void *ptr)
34
34
  if (bucket) {
35
35
  if (bucket->handle) {
36
36
  lcb_destroy(bucket->handle);
37
+ lcb_destroy_io_ops(bucket->io);
37
38
  }
38
39
  xfree(bucket->authority);
39
40
  xfree(bucket->hostname);
@@ -124,6 +125,14 @@ do_scan_connection_options(struct bucket_st *bucket, int argc, VALUE *argv)
124
125
  bucket->bucket = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
125
126
  }
126
127
  if (TYPE(opts) == T_HASH) {
128
+ arg = rb_hash_aref(opts, sym_type);
129
+ if (arg != Qnil) {
130
+ if (arg == sym_cluster) {
131
+ bucket->type = LCB_TYPE_CLUSTER;
132
+ } else {
133
+ bucket->type = LCB_TYPE_BUCKET;
134
+ }
135
+ }
127
136
  arg = rb_hash_aref(opts, sym_node_list);
128
137
  if (arg != Qnil) {
129
138
  VALUE tt;
@@ -239,6 +248,7 @@ do_connect(struct bucket_st *bucket)
239
248
 
240
249
  if (bucket->handle) {
241
250
  lcb_destroy(bucket->handle);
251
+ lcb_destroy_io_ops(bucket->io);
242
252
  bucket->handle = NULL;
243
253
  bucket->io = NULL;
244
254
  }
@@ -248,11 +258,13 @@ do_connect(struct bucket_st *bucket)
248
258
  }
249
259
 
250
260
  memset(&create_opts, 0, sizeof(struct lcb_create_st));
251
- create_opts.v.v0.host = bucket->node_list ? bucket-> node_list : bucket->authority;
252
- create_opts.v.v0.user = bucket->username;
253
- create_opts.v.v0.passwd = bucket->password;
254
- create_opts.v.v0.bucket = bucket->bucket;
255
- create_opts.v.v0.io = bucket->io;
261
+ create_opts.version = 1;
262
+ create_opts.v.v1.type = bucket->type;
263
+ create_opts.v.v1.host = bucket->node_list ? bucket-> node_list : bucket->authority;
264
+ create_opts.v.v1.user = bucket->username;
265
+ create_opts.v.v1.passwd = bucket->password;
266
+ create_opts.v.v1.bucket = bucket->bucket;
267
+ create_opts.v.v1.io = bucket->io;
256
268
  err = lcb_create(&bucket->handle, &create_opts);
257
269
  if (err != LCB_SUCCESS) {
258
270
  rb_exc_raise(cb_check_error(err, "failed to create libcouchbase instance", Qnil));
@@ -266,10 +278,8 @@ do_connect(struct bucket_st *bucket)
266
278
  (void)lcb_set_stat_callback(bucket->handle, stat_callback);
267
279
  (void)lcb_set_arithmetic_callback(bucket->handle, arithmetic_callback);
268
280
  (void)lcb_set_version_callback(bucket->handle, version_callback);
269
- (void)lcb_set_view_complete_callback(bucket->handle, http_complete_callback);
270
- (void)lcb_set_view_data_callback(bucket->handle, http_data_callback);
271
- (void)lcb_set_management_complete_callback(bucket->handle, http_complete_callback);
272
- (void)lcb_set_management_data_callback(bucket->handle, http_data_callback);
281
+ (void)lcb_set_http_complete_callback(bucket->handle, http_complete_callback);
282
+ (void)lcb_set_http_data_callback(bucket->handle, http_data_callback);
273
283
  (void)lcb_set_observe_callback(bucket->handle, observe_callback);
274
284
  (void)lcb_set_unlock_callback(bucket->handle, unlock_callback);
275
285
 
@@ -281,6 +291,7 @@ do_connect(struct bucket_st *bucket)
281
291
  err = lcb_connect(bucket->handle);
282
292
  if (err != LCB_SUCCESS) {
283
293
  lcb_destroy(bucket->handle);
294
+ lcb_destroy_io_ops(bucket->io);
284
295
  bucket->handle = NULL;
285
296
  bucket->io = NULL;
286
297
  rb_exc_raise(cb_check_error(err, "failed to connect libcouchbase instance to server", Qnil));
@@ -289,6 +300,7 @@ do_connect(struct bucket_st *bucket)
289
300
  lcb_wait(bucket->handle);
290
301
  if (bucket->exception != Qnil) {
291
302
  lcb_destroy(bucket->handle);
303
+ lcb_destroy_io_ops(bucket->io);
292
304
  bucket->handle = NULL;
293
305
  bucket->io = NULL;
294
306
  rb_exc_raise(bucket->exception);
@@ -391,6 +403,7 @@ cb_bucket_init(int argc, VALUE *argv, VALUE self)
391
403
 
392
404
  bucket->self = self;
393
405
  bucket->exception = Qnil;
406
+ bucket->type = LCB_TYPE_BUCKET;
394
407
  bucket->hostname = strdup("localhost");
395
408
  bucket->port = 8091;
396
409
  bucket->pool = strdup("default");
@@ -1060,7 +1073,7 @@ cb_bucket_run(int argc, VALUE *argv, VALUE self)
1060
1073
  cb_bucket_stop(VALUE self)
1061
1074
  {
1062
1075
  struct bucket_st *bucket = DATA_PTR(self);
1063
- bucket->io->stop_event_loop(bucket->io);
1076
+ lcb_breakout(bucket->handle);
1064
1077
  return Qnil;
1065
1078
  }
1066
1079
 
@@ -1080,6 +1093,7 @@ cb_bucket_disconnect(VALUE self)
1080
1093
 
1081
1094
  if (bucket->handle) {
1082
1095
  lcb_destroy(bucket->handle);
1096
+ lcb_destroy_io_ops(bucket->io);
1083
1097
  bucket->handle = NULL;
1084
1098
  bucket->io = NULL;
1085
1099
  return Qtrue;
@@ -41,6 +41,7 @@ ID sym_cas;
41
41
  ID sym_chunked;
42
42
  ID sym_content_type;
43
43
  ID sym_create;
44
+ ID sym_cluster;
44
45
  ID sym_decrement;
45
46
  ID sym_default_flags;
46
47
  ID sym_default_format;
@@ -156,6 +157,7 @@ VALUE eConnectError; /* LCB_CONNECT_ERROR = 0x17 */
156
157
  VALUE eBucketNotFoundError; /* LCB_BUCKET_ENOENT = 0x18 */
157
158
  VALUE eClientNoMemoryError; /* LCB_CLIENT_ENOMEM = 0x19 */
158
159
  VALUE eClientTmpFailError; /* LCB_CLIENT_ETMPFAIL = 0x20 */
160
+ VALUE eBadHandleError; /* LCB_EBADHANDLE = 0x21 */
159
161
 
160
162
 
161
163
  /* Ruby Extension initializer */
@@ -330,6 +332,14 @@ Init_couchbase_ext(void)
330
332
  * @since 1.1.0
331
333
  */
332
334
  eConnectError = rb_define_class_under(mError, "Connect", eBaseError);
335
+ /* Document-class: Couchbase::Error::BadHandle
336
+ * Invalid handle type.
337
+ *
338
+ * The requested operation isn't allowed for given type.
339
+ *
340
+ * @since 1.2.0
341
+ */
342
+ eBadHandleError = rb_define_class_under(mError, "BadHandle", eBaseError);
333
343
 
334
344
  /* Document-method: error
335
345
  *
@@ -362,7 +372,9 @@ Init_couchbase_ext(void)
362
372
  * 0x16 :: LCB_ETIMEDOUT (Operation timed out)
363
373
  * 0x17 :: LCB_CONNECT_ERROR (Connection failure)
364
374
  * 0x18 :: LCB_BUCKET_ENOENT (No such bucket)
365
- * 0x18 :: LCB_CLIENT_ENOMEM (Out of memory on the client)
375
+ * 0x19 :: LCB_CLIENT_ENOMEM (Out of memory on the client)
376
+ * 0x20 :: LCB_CLIENT_ETMPFAIL (Temporary failure on the client)
377
+ * 0x21 :: LCB_EBADHANDLE (Invalid handle type)
366
378
  *
367
379
  * @since 1.0.0
368
380
  *
@@ -911,6 +923,7 @@ Init_couchbase_ext(void)
911
923
  sym_chunked = ID2SYM(rb_intern("chunked"));
912
924
  sym_content_type = ID2SYM(rb_intern("content_type"));
913
925
  sym_create = ID2SYM(rb_intern("create"));
926
+ sym_cluster = ID2SYM(rb_intern("cluster"));
914
927
  sym_decrement = ID2SYM(rb_intern("decrement"));
915
928
  sym_default_flags = ID2SYM(rb_intern("default_flags"));
916
929
  sym_default_format = ID2SYM(rb_intern("default_format"));
@@ -23,6 +23,9 @@
23
23
  #endif
24
24
 
25
25
  #include "couchbase_config.h"
26
+ #ifdef HAVE_STDINT_H
27
+ #include <stdint.h>
28
+ #endif
26
29
  #ifndef HAVE_GETHRTIME
27
30
  typedef uint64_t hrtime_t;
28
31
  extern hrtime_t gethrtime(void);
@@ -65,6 +68,7 @@ extern hrtime_t gethrtime(void);
65
68
  struct bucket_st
66
69
  {
67
70
  lcb_t handle;
71
+ lcb_type_t type;
68
72
  struct lcb_io_opt_st *io;
69
73
  uint16_t port;
70
74
  char *authority;
@@ -155,6 +159,7 @@ extern ID sym_body;
155
159
  extern ID sym_bucket;
156
160
  extern ID sym_cas;
157
161
  extern ID sym_chunked;
162
+ extern ID sym_cluster;
158
163
  extern ID sym_content_type;
159
164
  extern ID sym_create;
160
165
  extern ID sym_decrement;
@@ -272,6 +277,7 @@ extern VALUE eConnectError; /* LCB_CONNECT_ERROR = 0x17 */
272
277
  extern VALUE eBucketNotFoundError; /* LCB_BUCKET_ENOENT = 0x18 */
273
278
  extern VALUE eClientNoMemoryError; /* LCB_CLIENT_ENOMEM = 0x19 */
274
279
  extern VALUE eClientTmpFailError; /* LCB_CLIENT_ETMPFAIL = 0x20 */
280
+ extern VALUE eBadHandleError; /* LCB_EBADHANDLE = 0x21 */
275
281
 
276
282
  void strip_key_prefix(struct bucket_st *bucket, VALUE key);
277
283
  VALUE cb_check_error(lcb_error_t rc, const char *msg, VALUE key);
@@ -119,8 +119,7 @@ if try_compile(<<-SRC)
119
119
  define("HAVE_STDARG_PROTOTYPES")
120
120
  end
121
121
 
122
-
123
- have_library("couchbase", "lcb_get", "libcouchbase/couchbase.h") or abort "You should install libcouchbase >= 2.0.0. See http://www.couchbase.com/develop/ for more details"
122
+ have_library("couchbase", "lcb_set_http_data_callback", "libcouchbase/couchbase.h") or abort "You should install libcouchbase >= 2.0.0beta2. See http://www.couchbase.com/develop/ for more details"
124
123
  have_header("mach/mach_time.h")
125
124
  have_header("stdint.h") or abort "Failed to locate stdint.h"
126
125
  have_header("sys/time.h")
@@ -23,6 +23,7 @@ http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *coo
23
23
  struct context_st *ctx = (struct context_st *)cookie;
24
24
  struct bucket_st *bucket = ctx->bucket;
25
25
  VALUE *rv = ctx->rv, key, val, res;
26
+ lcb_http_status_t status;
26
27
 
27
28
  ctx->request->completed = 1;
28
29
  key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
@@ -32,6 +33,7 @@ http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *coo
32
33
  cb_gc_protect(bucket, ctx->exception);
33
34
  }
34
35
  val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
36
+ status = resp->v.v0.status;
35
37
  if (resp->v.v0.headers) {
36
38
  cb_build_headers(ctx, resp->v.v0.headers);
37
39
  cb_gc_unprotect(bucket, ctx->headers_val);
@@ -39,6 +41,7 @@ http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *coo
39
41
  if (ctx->extended) {
40
42
  res = rb_class_new_instance(0, NULL, cResult);
41
43
  rb_ivar_set(res, id_iv_error, ctx->exception);
44
+ rb_ivar_set(res, id_iv_status, status ? INT2FIX(status) : Qnil);
42
45
  rb_ivar_set(res, id_iv_operation, sym_http_request);
43
46
  rb_ivar_set(res, id_iv_key, key);
44
47
  rb_ivar_set(res, id_iv_value, val);
@@ -63,11 +66,13 @@ http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie,
63
66
  struct context_st *ctx = (struct context_st *)cookie;
64
67
  struct bucket_st *bucket = ctx->bucket;
65
68
  VALUE key, val, res;
69
+ lcb_http_status_t status;
66
70
 
67
71
  key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
68
72
  ctx->exception = cb_check_error_with_status(error,
69
73
  "failed to execute HTTP request", key, resp->v.v0.status);
70
74
  val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
75
+ status = resp->v.v0.status;
71
76
  if (ctx->exception != Qnil) {
72
77
  cb_gc_protect(bucket, ctx->exception);
73
78
  lcb_cancel_http_request(bucket->handle, request);
@@ -79,6 +84,7 @@ http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie,
79
84
  if (ctx->extended) {
80
85
  res = rb_class_new_instance(0, NULL, cResult);
81
86
  rb_ivar_set(res, id_iv_error, ctx->exception);
87
+ rb_ivar_set(res, id_iv_status, status ? INT2FIX(status) : Qnil);
82
88
  rb_ivar_set(res, id_iv_operation, sym_http_request);
83
89
  rb_ivar_set(res, id_iv_key, key);
84
90
  rb_ivar_set(res, id_iv_value, val);
@@ -305,7 +311,7 @@ cb_http_request_perform(VALUE self)
305
311
  cb_http_request_pause(VALUE self)
306
312
  {
307
313
  struct http_request_st *req = DATA_PTR(self);
308
- req->bucket->io->stop_event_loop(req->bucket->io);
314
+ lcb_breakout(req->bucket->handle);
309
315
  return Qnil;
310
316
  }
311
317
 
@@ -41,7 +41,7 @@ cb_result_success_p(VALUE self)
41
41
  VALUE
42
42
  cb_result_inspect(VALUE self)
43
43
  {
44
- VALUE str, attr, error;
44
+ VALUE str, attr;
45
45
  char buf[100];
46
46
 
47
47
  str = rb_str_buf_new2("#<");
@@ -49,18 +49,15 @@ cb_result_inspect(VALUE self)
49
49
  snprintf(buf, 100, ":%p", (void *)self);
50
50
  rb_str_buf_cat2(str, buf);
51
51
 
52
- attr = rb_ivar_get(self, id_iv_error);
52
+ attr = rb_ivar_get(self, id_iv_operation);
53
53
  if (RTEST(attr)) {
54
- error = rb_ivar_get(attr, id_iv_error);
55
- } else {
56
- error = INT2FIX(0);
54
+ rb_str_buf_cat2(str, " operation=");
55
+ rb_str_append(str, rb_inspect(attr));
57
56
  }
58
- rb_str_buf_cat2(str, " error=0x");
59
- rb_str_append(str, rb_funcall(error, id_to_s, 1, INT2FIX(16)));
60
57
 
61
- attr = rb_ivar_get(self, id_iv_operation);
58
+ attr = rb_ivar_get(self, id_iv_error);
62
59
  if (RTEST(attr)) {
63
- rb_str_buf_cat2(str, " operation=");
60
+ rb_str_buf_cat2(str, " error=");
64
61
  rb_str_append(str, rb_inspect(attr));
65
62
  }
66
63
 
@@ -150,6 +150,12 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key,
150
150
  case LCB_CLIENT_ENOMEM:
151
151
  klass = eClientNoMemoryError;
152
152
  break;
153
+ case LCB_CLIENT_ETMPFAIL:
154
+ klass = eClientTmpFailError;
155
+ break;
156
+ case LCB_EBADHANDLE:
157
+ klass = eBadHandleError;
158
+ break;
153
159
  case LCB_ERROR:
154
160
  /* fall through */
155
161
  default:
@@ -184,7 +184,7 @@ module ActiveSupport
184
184
  instrument(:read_multi, names, options) do
185
185
  @data.get(names, options)
186
186
  end
187
- rescue Couchbase::Error::Base => e
187
+ rescue ::Couchbase::Error::Base => e
188
188
  logger.error("#{e.class}: #{e.message}") if logger
189
189
  raise if @raise_errors
190
190
  false
@@ -245,7 +245,7 @@ module ActiveSupport
245
245
  payload[:amount] = amount if payload
246
246
  @data.incr(name, amount, options)
247
247
  end
248
- rescue Couchbase::Error::Base => e
248
+ rescue ::Couchbase::Error::Base => e
249
249
  logger.error("#{e.class}: #{e.message}") if logger
250
250
  raise if @raise_errors
251
251
  false
@@ -277,7 +277,7 @@ module ActiveSupport
277
277
  payload[:amount] = amount if payload
278
278
  @data.decr(name, amount, options)
279
279
  end
280
- rescue Couchbase::Error::Base => e
280
+ rescue ::Couchbase::Error::Base => e
281
281
  logger.error("#{e.class}: #{e.message}") if logger
282
282
  raise if @raise_errors
283
283
  false
@@ -297,7 +297,7 @@ module ActiveSupport
297
297
  # Read an entry from the cache.
298
298
  def read_entry(key, options) # :nodoc:
299
299
  @data.get(key, options)
300
- rescue Couchbase::Error::Base => e
300
+ rescue ::Couchbase::Error::Base => e
301
301
  logger.error("#{e.class}: #{e.message}") if logger
302
302
  raise if @raise_errors
303
303
  nil
@@ -314,7 +314,7 @@ module ActiveSupport
314
314
  options[:ttl] ||= ttl
315
315
  end
316
316
  @data.send(method, key, value, options)
317
- rescue Couchbase::Error::Base => e
317
+ rescue ::Couchbase::Error::Base => e
318
318
  logger.error("#{e.class}: #{e.message}") if logger
319
319
  raise if @raise_errors
320
320
  false
@@ -323,7 +323,7 @@ module ActiveSupport
323
323
  # Delete an entry from the cache.
324
324
  def delete_entry(key, options) # :nodoc:
325
325
  @data.delete(key, options)
326
- rescue Couchbase::Error::Base => e
326
+ rescue ::Couchbase::Error::Base => e
327
327
  logger.error("#{e.class}: #{e.message}") if logger
328
328
  raise if @raise_errors
329
329
  false
@@ -26,6 +26,7 @@ require 'couchbase/bucket'
26
26
  require 'couchbase/view_row'
27
27
  require 'couchbase/view'
28
28
  require 'couchbase/result'
29
+ require 'couchbase/cluster'
29
30
 
30
31
  # Couchbase ruby client
31
32
  module Couchbase
@@ -238,6 +238,9 @@ module Couchbase
238
238
  # end
239
239
  # end
240
240
  def flush
241
+ if !async? && block_given?
242
+ raise ArgumentError, "synchronous mode doesn't support callbacks"
243
+ end
241
244
  req = make_http_request("/pools/default/buckets/#{bucket}/controller/doFlush",
242
245
  :type => :management, :method => :post, :extended => true)
243
246
  res = nil
@@ -0,0 +1,105 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ module Couchbase
19
+
20
+ class Cluster
21
+
22
+ # Establish connection to the cluster for administration
23
+ #
24
+ # @param [Hash] options The connection parameter
25
+ # @option options [String] :username The username
26
+ # @option options [String] :password The password
27
+ # @option options [String] :pool ("default") The pool name
28
+ # @option options [String] :hostname ("localhost") The hostname
29
+ # @option options [String] :port (8091) The port
30
+ def initialize(options = {})
31
+ if options[:username].nil? || options[:password].nil?
32
+ raise ArgumentError, "username and password mandatory to connect to the cluster"
33
+ end
34
+ @connection = Bucket.new(options.merge(:type => :cluster))
35
+ end
36
+
37
+ # Create data bucket
38
+ #
39
+ # @param [String] name The name of the bucket
40
+ # @param [Hash] options The bucket parameters
41
+ # @option options [String] :bucket_type ("couchbase") The type of the
42
+ # bucket. Possible values are "memcached" and "couchbase".
43
+ # @option options [Fixnum] :ram_quota (100) The RAM quota in megabytes.
44
+ # @option options [Fixnum] :replica_number (1) The number of replicas of
45
+ # each document
46
+ # @option options [String] :auth_type ("sasl") The authentication type.
47
+ # Possible values are "sasl" and "none". Note you should specify free
48
+ # port for "none"
49
+ # @option options [Fixnum] :proxy_port The port for moxi
50
+ def create_bucket(name, options = {})
51
+ defaults = {
52
+ :type => "couchbase",
53
+ :ram_quota => 100,
54
+ :replica_number => 1,
55
+ :auth_type => "sasl",
56
+ :sasl_password => "",
57
+ :proxy_port => nil
58
+ }
59
+ options = defaults.merge(options)
60
+ params = {"name" => name}
61
+ params["bucketType"] = options[:type]
62
+ params["ramQuotaMB"] = options[:ram_quota]
63
+ params["replicaNumber"] = options[:replica_number]
64
+ params["authType"] = options[:auth_type]
65
+ params["saslPassword"] = options[:sasl_password]
66
+ params["proxyPort"] = options[:proxy_port]
67
+ payload = Utils.encode_params(params.reject!{|k, v| v.nil?})
68
+ request = @connection.make_http_request("/pools/default/buckets",
69
+ :content_type => "application/x-www-form-urlencoded",
70
+ :type => :management,
71
+ :method => :post,
72
+ :extended => true,
73
+ :body => payload)
74
+ response = nil
75
+ request.on_body do |r|
76
+ response = r
77
+ response.instance_variable_set("@operation", :create_bucket)
78
+ yield(response) if block_given?
79
+ end
80
+ request.continue
81
+ response
82
+ end
83
+
84
+ # Delete the data bucket
85
+ #
86
+ # @param [String] name The name of the bucket
87
+ # @param [Hash] options
88
+ def delete_bucket(name, options = {})
89
+ request = @connection.make_http_request("/pools/default/buckets/#{name}",
90
+ :type => :management,
91
+ :method => :delete,
92
+ :extended => true)
93
+ response = nil
94
+ request.on_body do |r|
95
+ response = r
96
+ response.instance_variable_set("@operation", :delete_bucket)
97
+ yield(response) if block_given?
98
+ end
99
+ request.continue
100
+ response
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -19,11 +19,8 @@ module Couchbase
19
19
 
20
20
  class Utils
21
21
 
22
- def self.build_query(uri, params = nil)
23
- uri = uri.dup
24
- return uri if params.nil? || params.empty?
25
- uri << "?"
26
- uri << params.map do |k, v|
22
+ def self.encode_params(params)
23
+ params.map do |k, v|
27
24
  next if !v && k.to_s == "group"
28
25
  if %w{key keys startkey endkey start_key end_key}.include?(k.to_s)
29
26
  v = MultiJson.dump(v)
@@ -36,6 +33,12 @@ module Couchbase
36
33
  end.compact.join("&")
37
34
  end
38
35
 
36
+ def self.build_query(uri, params = nil)
37
+ uri = uri.dup
38
+ return uri if params.nil? || params.empty?
39
+ uri << "?" << encode_params(params)
40
+ end
41
+
39
42
  def self.escape(s)
40
43
  s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/nu) {
41
44
  '%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
@@ -17,5 +17,5 @@
17
17
 
18
18
  # Couchbase ruby client
19
19
  module Couchbase
20
- VERSION = "1.2.0.z.beta2"
20
+ VERSION = "1.2.0.z.beta3"
21
21
  end
@@ -90,7 +90,7 @@ module Rack
90
90
  def with_lock(env, default = nil)
91
91
  @mutex.lock if env['rack.multithread']
92
92
  yield
93
- rescue Couchbase::Error::Connect, Couchbase::Error::Timeout
93
+ rescue ::Couchbase::Error::Connect, ::Couchbase::Error::Timeout
94
94
  if $VERBOSE
95
95
  warn "#{self} is unable to find Couchbase server."
96
96
  warn $!.inspect
@@ -84,7 +84,7 @@ namespace :ports do
84
84
  directory "ports"
85
85
 
86
86
  task :libcouchbase => ["ports"] do
87
- recipe = MiniPortile.new "libcouchbase", "2.0.0beta_5_g970a292"
87
+ recipe = MiniPortile.new "libcouchbase", "2.0.0beta2_1_gf60b9fe"
88
88
  recipe.files << "http://packages.couchbase.com/clients/c/libcouchbase-#{recipe.version}.tar.gz"
89
89
  recipe.configure_options.push("--disable-debug",
90
90
  "--disable-dependency-tracking",
@@ -154,27 +154,31 @@ class TestAsync < MiniTest::Unit::TestCase
154
154
  end
155
155
 
156
156
  def test_nested_async_flush_set
157
- connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
158
- cas = connection.set(uniq_id, "foo")
159
- res = {}
157
+ if @mock.real?
158
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
159
+ cas = connection.set(uniq_id, "foo")
160
+ res = {}
160
161
 
161
- connection.run do |conn|
162
- conn.flush do |res1|
163
- assert res1.success?
164
- id = uniq_id(res1.node)
165
- res[id] = false
166
- conn.set(id, true) do |res2|
167
- res[id] = res2.cas
162
+ connection.run do |conn|
163
+ conn.flush do |res1|
164
+ assert res1.success?
165
+ id = uniq_id(res1.node)
166
+ res[id] = false
167
+ conn.set(id, true) do |res2|
168
+ res[id] = res2.cas
169
+ end
168
170
  end
169
171
  end
170
- end
171
172
 
172
- assert_raises(Couchbase::Error::NotFound) do
173
- connection.get(uniq_id)
174
- end
175
- res.keys.each do |key|
176
- assert res[key].is_a?(Numeric)
177
- assert connection.get(key)
173
+ assert_raises(Couchbase::Error::NotFound) do
174
+ connection.get(uniq_id)
175
+ end
176
+ res.keys.each do |key|
177
+ assert res[key].is_a?(Numeric)
178
+ assert connection.get(key)
179
+ end
180
+ else
181
+ skip("REST FLUSH isn't implemented in CouchbaseMock.jar yet")
178
182
  end
179
183
  end
180
184
 
metadata CHANGED
@@ -1,215 +1,212 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: couchbase
3
- version: !ruby/object:Gem::Version
4
- version: 1.2.0.z.beta2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 8279698299
5
5
  prerelease: 6
6
+ segments:
7
+ - 1
8
+ - 2
9
+ - 0
10
+ - z
11
+ - beta
12
+ - 3
13
+ version: 1.2.0.z.beta3
6
14
  platform: ruby
7
- authors:
15
+ authors:
8
16
  - Couchbase
9
17
  autorequire:
10
18
  bindir: bin
11
19
  cert_chain: []
12
- date: 2012-09-21 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: yaji
16
- requirement: !ruby/object:Gem::Requirement
20
+
21
+ date: 2012-10-16 00:00:00 +03:00
22
+ default_executable:
23
+ dependencies:
24
+ - !ruby/object:Gem::Dependency
25
+ type: :runtime
26
+ requirement: &id001 !ruby/object:Gem::Requirement
17
27
  none: false
18
- requirements:
28
+ requirements:
19
29
  - - ~>
20
- - !ruby/object:Gem::Version
30
+ - !ruby/object:Gem::Version
31
+ hash: 23
32
+ segments:
33
+ - 0
34
+ - 3
35
+ - 2
21
36
  version: 0.3.2
22
- type: :runtime
37
+ name: yaji
38
+ version_requirements: *id001
23
39
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
40
+ - !ruby/object:Gem::Dependency
41
+ type: :runtime
42
+ requirement: &id002 !ruby/object:Gem::Requirement
25
43
  none: false
26
- requirements:
44
+ requirements:
27
45
  - - ~>
28
- - !ruby/object:Gem::Version
29
- version: 0.3.2
30
- - !ruby/object:Gem::Dependency
46
+ - !ruby/object:Gem::Version
47
+ hash: 15
48
+ segments:
49
+ - 1
50
+ - 0
51
+ version: "1.0"
31
52
  name: multi_json
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ~>
36
- - !ruby/object:Gem::Version
37
- version: '1.0'
38
- type: :runtime
53
+ version_requirements: *id002
39
54
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: '1.0'
46
- - !ruby/object:Gem::Dependency
47
- name: rake
48
- requirement: !ruby/object:Gem::Requirement
55
+ - !ruby/object:Gem::Dependency
56
+ type: :development
57
+ requirement: &id003 !ruby/object:Gem::Requirement
49
58
  none: false
50
- requirements:
59
+ requirements:
51
60
  - - ~>
52
- - !ruby/object:Gem::Version
61
+ - !ruby/object:Gem::Version
62
+ hash: 49
63
+ segments:
64
+ - 0
65
+ - 8
66
+ - 7
53
67
  version: 0.8.7
54
- type: :development
68
+ name: rake
69
+ version_requirements: *id003
55
70
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
71
+ - !ruby/object:Gem::Dependency
72
+ type: :development
73
+ requirement: &id004 !ruby/object:Gem::Requirement
57
74
  none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 0.8.7
62
- - !ruby/object:Gem::Dependency
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
63
82
  name: minitest
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
83
+ version_requirements: *id004
71
84
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- - !ruby/object:Gem::Dependency
79
- name: rake-compiler
80
- requirement: !ruby/object:Gem::Requirement
85
+ - !ruby/object:Gem::Dependency
86
+ type: :development
87
+ requirement: &id005 !ruby/object:Gem::Requirement
81
88
  none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 9
93
+ segments:
94
+ - 0
95
+ - 7
96
+ - 5
85
97
  version: 0.7.5
86
- type: :development
98
+ name: rake-compiler
99
+ version_requirements: *id005
87
100
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
101
+ - !ruby/object:Gem::Dependency
102
+ type: :development
103
+ requirement: &id006 !ruby/object:Gem::Requirement
89
104
  none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: 0.7.5
94
- - !ruby/object:Gem::Dependency
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
95
112
  name: rdiscount
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
- type: :development
113
+ version_requirements: *id006
103
114
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
115
+ - !ruby/object:Gem::Dependency
116
+ type: :development
117
+ requirement: &id007 !ruby/object:Gem::Requirement
105
118
  none: false
106
- requirements:
107
- - - ! '>='
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- - !ruby/object:Gem::Dependency
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
111
126
  name: yard
112
- requirement: !ruby/object:Gem::Requirement
113
- none: false
114
- requirements:
115
- - - ! '>='
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
127
+ version_requirements: *id007
119
128
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
129
+ - !ruby/object:Gem::Dependency
130
+ type: :development
131
+ requirement: &id008 !ruby/object:Gem::Requirement
121
132
  none: false
122
- requirements:
123
- - - ! '>='
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ hash: 3
137
+ segments:
138
+ - 0
139
+ version: "0"
127
140
  name: yard-xml
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ! '>='
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- type: :development
141
+ version_requirements: *id008
135
142
  prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
143
+ - !ruby/object:Gem::Dependency
144
+ type: :development
145
+ requirement: &id009 !ruby/object:Gem::Requirement
137
146
  none: false
138
- requirements:
139
- - - ! '>='
140
- - !ruby/object:Gem::Version
141
- version: '0'
142
- - !ruby/object:Gem::Dependency
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ hash: 3
151
+ segments:
152
+ - 0
153
+ version: "0"
143
154
  name: mini_portile
144
- requirement: !ruby/object:Gem::Requirement
145
- none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
150
- type: :development
155
+ version_requirements: *id009
151
156
  prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ! '>='
156
- - !ruby/object:Gem::Version
157
- version: '0'
158
- - !ruby/object:Gem::Dependency
159
- name: yajl-ruby
160
- requirement: !ruby/object:Gem::Requirement
161
- none: false
162
- requirements:
163
- - - ~>
164
- - !ruby/object:Gem::Version
165
- version: 1.1.0
157
+ - !ruby/object:Gem::Dependency
166
158
  type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
159
+ requirement: &id010 !ruby/object:Gem::Requirement
169
160
  none: false
170
- requirements:
161
+ requirements:
171
162
  - - ~>
172
- - !ruby/object:Gem::Version
163
+ - !ruby/object:Gem::Version
164
+ hash: 19
165
+ segments:
166
+ - 1
167
+ - 1
168
+ - 0
173
169
  version: 1.1.0
174
- - !ruby/object:Gem::Dependency
175
- name: debugger
176
- requirement: !ruby/object:Gem::Requirement
177
- none: false
178
- requirements:
179
- - - ! '>='
180
- - !ruby/object:Gem::Version
181
- version: '0'
170
+ name: yajl-ruby
171
+ version_requirements: *id010
172
+ prerelease: false
173
+ - !ruby/object:Gem::Dependency
182
174
  type: :development
175
+ requirement: &id011 !ruby/object:Gem::Requirement
176
+ none: false
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ hash: 3
181
+ segments:
182
+ - 0
183
+ version: "0"
184
+ name: ruby-debug
185
+ version_requirements: *id011
183
186
  prerelease: false
184
- version_requirements: !ruby/object:Gem::Requirement
187
+ - !ruby/object:Gem::Dependency
188
+ type: :development
189
+ requirement: &id012 !ruby/object:Gem::Requirement
185
190
  none: false
186
- requirements:
187
- - - ! '>='
188
- - !ruby/object:Gem::Version
189
- version: '0'
190
- - !ruby/object:Gem::Dependency
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ hash: 3
195
+ segments:
196
+ - 0
197
+ version: "0"
191
198
  name: active_support
192
- requirement: !ruby/object:Gem::Requirement
193
- none: false
194
- requirements:
195
- - - ! '>='
196
- - !ruby/object:Gem::Version
197
- version: '0'
198
- type: :development
199
+ version_requirements: *id012
199
200
  prerelease: false
200
- version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
- requirements:
203
- - - ! '>='
204
- - !ruby/object:Gem::Version
205
- version: '0'
206
201
  description: The official client library for use with Couchbase Server.
207
202
  email: support@couchbase.com
208
203
  executables: []
209
- extensions:
204
+
205
+ extensions:
210
206
  - ext/couchbase_ext/extconf.rb
211
207
  extra_rdoc_files: []
212
- files:
208
+
209
+ files:
213
210
  - .gitignore
214
211
  - .travis.yml
215
212
  - .yardopts
@@ -243,6 +240,7 @@ files:
243
240
  - lib/active_support/cache/couchbase_store.rb
244
241
  - lib/couchbase.rb
245
242
  - lib/couchbase/bucket.rb
243
+ - lib/couchbase/cluster.rb
246
244
  - lib/couchbase/result.rb
247
245
  - lib/couchbase/utils.rb
248
246
  - lib/couchbase/version.rb
@@ -276,29 +274,41 @@ files:
276
274
  - test/test_unlock.rb
277
275
  - test/test_utils.rb
278
276
  - test/test_version.rb
277
+ has_rdoc: true
279
278
  homepage: http://couchbase.org
280
- licenses:
279
+ licenses:
281
280
  - ASL-2
282
281
  post_install_message:
283
282
  rdoc_options: []
284
- require_paths:
283
+
284
+ require_paths:
285
285
  - lib
286
- required_ruby_version: !ruby/object:Gem::Requirement
286
+ required_ruby_version: !ruby/object:Gem::Requirement
287
287
  none: false
288
- requirements:
289
- - - ! '>='
290
- - !ruby/object:Gem::Version
291
- version: '0'
292
- required_rubygems_version: !ruby/object:Gem::Requirement
288
+ requirements:
289
+ - - ">="
290
+ - !ruby/object:Gem::Version
291
+ hash: 3
292
+ segments:
293
+ - 0
294
+ version: "0"
295
+ required_rubygems_version: !ruby/object:Gem::Requirement
293
296
  none: false
294
- requirements:
295
- - - ! '>'
296
- - !ruby/object:Gem::Version
297
+ requirements:
298
+ - - ">"
299
+ - !ruby/object:Gem::Version
300
+ hash: 25
301
+ segments:
302
+ - 1
303
+ - 3
304
+ - 1
297
305
  version: 1.3.1
298
306
  requirements: []
307
+
299
308
  rubyforge_project:
300
- rubygems_version: 1.8.23
309
+ rubygems_version: 1.6.2
301
310
  signing_key:
302
311
  specification_version: 3
303
312
  summary: Couchbase ruby driver
304
313
  test_files: []
314
+