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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+