Merge lp:~zorba-coders/zorba/couchbase-module-new-options into lp:zorba/couchbase-module

Proposed by Juan Zacarias
Status: Merged
Approved by: Sorin Marian Nasoi
Approved revision: 37
Merged at revision: 35
Proposed branch: lp:~zorba-coders/zorba/couchbase-module-new-options
Merge into: lp:zorba/couchbase-module
Diff against target: 489 lines (+271/-22)
5 files modified
examples/example.xq (+1/-1)
src/couchbase.xq (+41/-3)
src/couchbase.xq.src/couchbase.cpp (+170/-8)
src/couchbase.xq.src/couchbase.h (+49/-4)
test/Queries/couchbase_module/view.xq (+10/-6)
To merge this branch: bzr merge lp:~zorba-coders/zorba/couchbase-module-new-options
Reviewer Review Type Date Requested Status
Sorin Marian Nasoi Approve
Chris Hillery Approve
Review via email: mp+143187@code.launchpad.net

Commit message

*Added new options to the cb:view Function:
-"limit" option, allows the user to limit the numbers of results shown by the view
-"stale" option, allows the user to specify when to update the view: update after the view is returned(default by couchbase), update before the view is returned, and don't update if the view function is called.

*Added a new option to the cb:put-text and cb:put-binary Functions:
-"wait" option, allows the user to wait for confirmation from couchbase that the key/value pair was stored in disk.

Modified test view.xq using the new options so it doesn't fail when ran for the first time.

To post a comment you must log in.
Revision history for this message
Chris Hillery (ceejatec) wrote :

I was a bit confused by the choices for parameter values for "stale" and "wait", but it looks like those come directly from Couchbase itself, so OK then.

One change: This failed on the RQ the first time the test was run, but not on later RQ runs. That implies to me that later RQ runs are probably seeing leftover data from the earlier runs. The view.xq test case should clean up after itself by deleting the value that it inserts, at least IMHO. Possibly other test cases have a similar issue; please check.

review: Needs Fixing
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job couchbase-module-new-options-2013-01-14T22-34-42.475Z is finished. The final status was:

All tests succeeded!

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 1 Needs Fixing, 1 Pending.

Revision history for this message
Juan Zacarias (juan457) wrote :

It didn't fail because the created views remain on the database. They are not deleted since they shouldn't be cleaned with the module, but the views are database management work. I will add a delete view just like the create view which are management functions.

37. By Juan Zacarias

Added a delete view function added it to view.xq test

Revision history for this message
Juan Zacarias (juan457) wrote :

Fixed

Revision history for this message
Chris Hillery (ceejatec) :
review: Approve
Revision history for this message
Sorin Marian Nasoi (sorin.marian.nasoi) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job couchbase-module-new-options-2013-01-18T06-35-46.187Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/example.xq'
2--- examples/example.xq 2013-01-10 07:59:35 +0000
3+++ examples/example.xq 2013-01-17 22:52:18 +0000
4@@ -7,7 +7,7 @@
5 "password" : null,
6 "bucket" : "default"});
7 variable $view-name := cb:create-view($instance, "zip", "zip", {"key" : "doc.state", "values" : "doc.pop"});
8-variable $data := cb:view($instance, $view-name);
9+variable $data := cb:view($instance, $view-name, {"stale" : "false"});
10 for $d in jn:members($data("rows"))
11 let $state := $d("key")
12 group by $state
13
14=== modified file 'src/couchbase.xq'
15--- src/couchbase.xq 2013-01-10 08:07:25 +0000
16+++ src/couchbase.xq 2013-01-17 22:52:18 +0000
17@@ -232,7 +232,10 @@
18 : @option "operation" type of operation, possible values are
19 : "add", "replace", "set", "append" and "prepend".
20 : @option "encoding" the encoding that should be used for the
21- : value (default is UTF-8).
22+ : value (default is UTF-8).
23+ : @option "wait" variable for setting if a wait for persistancy in
24+ : the storing key is needed, possible values are "persist"
25+ : and "false".
26 :
27 : @error cb:LCB0002 if any error occurs in the communication with
28 : the server.
29@@ -241,6 +244,7 @@
30 : @error cb:CB0006 if the given encoding is not supported.
31 : @error cb:CB0007 if any of the options is not supported.
32 : @error cb:CB0009 if the given expiration time is not an xs:integer.
33+ : @error cb:CB0011 if the stored Variable was not stored
34 :
35 : @return a empty sequence.
36 :)
37@@ -286,6 +290,9 @@
38 : expiration time in seconds.
39 : @option "operation" type of operation, possible values are
40 : "add", "replace", "set", "append" and "prepend".
41+ : @option "wait" variable for setting if a wait for persistancy in
42+ : the storing key is needed, possible values are "persist"
43+ : and "false".
44 :
45 : @error cb:LCB0002 if any error occurs in the communication with
46 : the server.
47@@ -293,6 +300,7 @@
48 : of values.
49 : @error cb:CB0007 if any of the options is not supported.
50 : @error cb:CB0009 if the given expiration time is not an xs:integer.
51+ : @error cb:CB0011 if the stored Variable was not stored
52 :
53 : @return a empty sequence.
54 :)
55@@ -365,8 +373,18 @@
56 : (e.g. "_design/test/_view/vies").
57 : @param $options JSONiq object with additional options
58 :
59- : @option "encoding" string with the name of the encoding of the returned
60- : strings (if not UTF-8).
61+ : @option Json object whith options for the querying the view. available options:
62+ : "encoding" string with the name of the encoding of the returned
63+ : strings (if not UTF-8).
64+ : "stale" option's value is a string with the type of stale to be used.
65+ : Valid values:
66+ : "ok" : the view is not updated
67+ : "false" : the view is updated before the function view is executed,
68+ : this options needs the key to be on disk before the call of the
69+ : view function.
70+ : "update_after" : the view is updated after the call of view
71+ : "limit" option's value is an integer which sets a number of how many
72+ : rows the view will show.
73 :
74 : @error cb:LCB0002 if any error occurs in the communication with
75 : the server.
76@@ -451,3 +469,23 @@
77 $view-names as xs:string*,
78 $options as object()*)
79 as xs:string* external;
80+
81+
82+(:~
83+ : Delete a document/view.
84+
85+ : If the document doesn't exists, function does nothing. All the views hold in the
86+ : Document are deleted, this function can't delete single views.
87+ :
88+ : @param $db connection reference
89+ : @param $doc-name name of the document to create.
90+ :
91+ : @error cb:LCB0002 if any error occurs in the communication with
92+ : the server.
93+ :
94+ : @return empty sequence.
95+ :)
96+declare %an:sequential function cb:delete-view(
97+ $db as xs:anyURI,
98+ $doc as xs:string*)
99+as xs:string* external;
100
101=== modified file 'src/couchbase.xq.src/couchbase.cpp'
102--- src/couchbase.xq.src/couchbase.cpp 2013-01-10 07:59:35 +0000
103+++ src/couchbase.xq.src/couchbase.cpp 2013-01-17 22:52:18 +0000
104@@ -89,6 +89,10 @@
105 {
106 lFunc = new CreateViewFunction(this);
107 }
108+ else if (localname == "delete-view")
109+ {
110+ lFunc = new DeleteViewFunction(this);
111+ }
112 }
113
114 return lFunc;
115@@ -190,6 +194,30 @@
116 return NULL;
117 }
118
119+String
120+ CouchbaseFunction::ViewOptions::getPathOptions()
121+{
122+ String lPathOptions("?");
123+ bool lAmp = false;
124+ if (theStaleOption != "")
125+ {
126+ lPathOptions.append(theStaleOption);
127+ lAmp = true;
128+ }
129+ if (theLimitOption != "")
130+ {
131+ if(lAmp)
132+ lPathOptions.append("&");
133+ lPathOptions.append(theLimitOption);
134+ lAmp = true;
135+ }
136+
137+ if (lPathOptions == "?")
138+ lPathOptions = "";
139+
140+ return lPathOptions;
141+}
142+
143 void
144 CouchbaseFunction::ViewOptions::setOptions(Item& aOptions)
145 {
146@@ -216,6 +244,42 @@
147 throwError("CB0006", lMsg.str().c_str());
148 }
149 }
150+ else if (lStrKey == "stale")
151+ {
152+ Item lValue = aOptions.getObjectValue(lStrKey);
153+ String lString = lValue.getStringValue();
154+ if (lString == "false")
155+ {
156+ theStaleOption ="stale=false";
157+ }
158+ else if (lString == "ok")
159+ {
160+ theStaleOption ="stale=ok";
161+ }
162+ else if (lString == "update_after")
163+ {
164+ theStaleOption ="stale=update_after";
165+ }
166+ else
167+ {
168+ std::ostringstream lMsg;
169+ lMsg << lStrKey << "=" << lString << ": option not supported";
170+ throwError("CB0007", lMsg.str().c_str());
171+ }
172+ }
173+ else if (lStrKey == "limit")
174+ {
175+ Item lValue = aOptions.getObjectValue(lStrKey);
176+ try
177+ {
178+ int lLimit = lValue.getIntValue();
179+ theLimitOption = "limit=" + lLimit;
180+ }
181+ catch (ZorbaException& e)
182+ {
183+ throwError("CB0009", " limit option must be an integer value");
184+ }
185+ }
186 else
187 {
188 std::ostringstream lMsg;
189@@ -371,6 +435,28 @@
190 throwError("CB0006", lMsg.str().c_str());
191 }
192 }
193+ else if (lStrKey == "wait")
194+ {
195+ Item lValue = aOptions.getObjectValue(lStrKey);
196+ String lStrValue = lValue.getStringValue();
197+ std::transform(
198+ lStrValue.begin(), lStrValue.end(),
199+ lStrValue.begin(), tolower);
200+ if (lStrValue == "persist")
201+ {
202+ theWaitType = CB_WAIT_PERSIST;
203+ }
204+ else if (lStrValue == "false")
205+ {
206+ theWaitType = CB_WAIT_FALSE;
207+ }
208+ else
209+ {
210+ std::ostringstream lMsg;
211+ lMsg << lStrKey << "=" << lStrValue << " : option not supported";
212+ throwError("CB0007", lMsg.str().c_str());
213+ }
214+ }
215 else
216 {
217 std::ostringstream lMsg;
218@@ -731,6 +817,26 @@
219 /*******************************************************************************
220 ******************************************************************************/
221
222+void CouchbaseFunction::observe_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_observe_resp_t *resp)
223+{
224+ if (error != LCB_SUCCESS)
225+ {
226+ libCouchbaseError (instance, error);
227+ }
228+
229+ PutOptions* lWait = (PutOptions*) cookie;
230+ //verify is coming from the master
231+ if (resp->v.v0.from_master > 0)
232+ {
233+ lcb_observe_t lStatus = resp->v.v0.status;if (lStatus == LCB_OBSERVE_NOT_FOUND)
234+ {
235+ throwError("CB0011", "Variable stored not found.");
236+ }
237+ //check for flag of persisntancy
238+ lWait->setWaiting(lStatus & LCB_OBSERVE_PERSISTED?false:true);
239+ }
240+}
241+
242 void CouchbaseFunction::put (lcb_t aInstance, Iterator_t aKeys, Iterator_t aValues, PutOptions aOptions)
243 {
244 lcb_error_t lError;
245@@ -800,9 +906,23 @@
246 {
247 libCouchbaseError (aInstance, lError);
248 }
249-
250-
251+ //Wait for store
252 lcb_wait(aInstance);
253+ //Check if wait for disk
254+ if (aOptions.getWaitType() != CB_WAIT_FALSE)
255+ {
256+ lcb_set_observe_callback(aInstance, observe_callback);
257+ PutOptions* lOptions = &aOptions;
258+ do {
259+ lcb_observe_cmd_t lObserve;
260+ lObserve.version = 0;
261+ lObserve.v.v0.key = lStrKey.c_str();
262+ lObserve.v.v0.nkey = lStrKey.size();
263+ lcb_observe_cmd_t* lCommands[1] = { &lObserve };
264+ lcb_observe(aInstance, lOptions, 1, lCommands);
265+ lcb_wait(aInstance);
266+ }while(lOptions->isWaiting());
267+ }
268 }
269
270 if (aValues->next(lValue))
271@@ -1005,19 +1125,23 @@
272 if (thePaths->next(lPath))
273 {
274 ViewOptions* lOptions = &theOptions;
275-
276+ String lPathOptions = lOptions->getPathOptions();
277+ String lPathString = lPath.getStringValue();
278+ if (lPathOptions != "")
279+ {
280+ lPathString.append(lPathOptions);
281+ }
282 lcb_http_request_t lReq;
283 lcb_http_cmd_t lCmd;
284 lCmd.version = 0;
285- lCmd.v.v0.path = lPath.getStringValue().c_str();
286- lCmd.v.v0.npath = lPath.getStringValue().size();
287+ lCmd.v.v0.path = lPathString.c_str();
288+ lCmd.v.v0.npath = lPathString.size();
289 lCmd.v.v0.body = NULL;
290 lCmd.v.v0.nbody = 0;
291 lCmd.v.v0.method = LCB_HTTP_METHOD_GET;
292 lCmd.v.v0.chunked = 1;
293 lCmd.v.v0.content_type = "application/json";
294 lcb_error_t err = lcb_make_http_request(theInstance, lOptions, LCB_HTTP_TYPE_VIEW, &lCmd, &lReq);
295-
296 if (err != LCB_SUCCESS)
297 {
298 libCouchbaseError (theInstance, err);
299@@ -1065,8 +1189,46 @@
300
301 /*******************************************************************************
302 ******************************************************************************/
303-
304-
305+zorba::ItemSequence_t
306+DeleteViewFunction::evaluate(
307+ const Arguments_t& aArgs,
308+ const zorba::StaticContext* aSctx,
309+ const zorba::DynamicContext* aDctx) const
310+{
311+ String lInstanceID = getOneStringArgument(aArgs, 0);
312+ lcb_t lInstance = getInstance(aDctx, lInstanceID);
313+
314+ Iterator_t lDocNames = getIterArgument(aArgs, 1);
315+ Item lDoc;
316+ lDocNames->open();
317+ while(lDocNames->next(lDoc))
318+ {
319+ String lPath = "_design/" + lDoc.getStringValue();
320+ lcb_http_request_t req;
321+ lcb_http_cmd_t cmd;
322+ cmd.version = 0;
323+ cmd.v.v0.path = lPath.c_str();
324+ cmd.v.v0.npath = lPath.size();
325+ cmd.v.v0.body = NULL;
326+ cmd.v.v0.nbody = 0;
327+ cmd.v.v0.method = LCB_HTTP_METHOD_DELETE;
328+ cmd.v.v0.chunked = false;
329+ cmd.v.v0.content_type = "application/json";
330+ lcb_error_t err = lcb_make_http_request(lInstance, NULL,
331+ LCB_HTTP_TYPE_VIEW, &cmd, &req);
332+
333+ if (err != LCB_SUCCESS)
334+ libCouchbaseError (lInstance, err);
335+
336+ lcb_wait(lInstance);
337+ }
338+ lDocNames->close();
339+
340+ return ItemSequence_t(new EmptySequence());
341+}
342+
343+/*******************************************************************************
344+ ******************************************************************************/
345 zorba::ItemSequence_t
346 CreateViewFunction::evaluate(
347 const Arguments_t& aArgs,
348
349=== modified file 'src/couchbase.xq.src/couchbase.h'
350--- src/couchbase.xq.src/couchbase.h 2013-01-10 06:51:21 +0000
351+++ src/couchbase.xq.src/couchbase.h 2013-01-17 22:52:18 +0000
352@@ -86,16 +86,25 @@
353
354 } lcb_storage_type_t;
355
356+ typedef enum
357+ {
358+ CB_WAIT_FALSE = 0x00,
359+ CB_WAIT_PERSIST = 0x01,
360+ CB_WAIT_REPLICATE = 0x02
361+ } cb_wait_type_t;
362+
363 class ViewOptions
364 {
365 protected:
366 String theEncoding;
367 String thePath;
368+ String theStaleOption;
369+ String theLimitOption;
370
371 public:
372 std::unique_ptr<std::stringstream>* theStream;
373
374- ViewOptions() : theEncoding("UTF-8"), thePath("") { theStream = NULL; }
375+ ViewOptions() : theEncoding("UTF-8"), thePath(""), theStaleOption(""), theLimitOption("") { theStream = NULL; }
376
377 ViewOptions(String& aPath) : theEncoding("UTF-8"), thePath(aPath) {}
378
379@@ -106,6 +115,8 @@
380 String getEncoding() { return theEncoding; }
381
382 String getPath() { return thePath; }
383+
384+ String getPathOptions();
385 };
386
387 class GetOptions
388@@ -137,17 +148,18 @@
389 class PutOptions
390 {
391 protected:
392-
393 lcb_storage_t theOperation;
394 lcb_storage_type_t theType;
395 unsigned int theExpTime;
396 String theEncoding;
397+ cb_wait_type_t theWaitType;
398+ bool theIsWaiting;
399
400 public:
401
402- PutOptions() : theOperation(LCB_ADD), theType(LCB_JSON), theExpTime(0), theEncoding("") { }
403+ PutOptions() : theOperation(LCB_ADD), theType(LCB_JSON), theExpTime(0), theEncoding(""), theWaitType(CB_WAIT_FALSE), theIsWaiting(false){ }
404
405- PutOptions(lcb_storage_type_t aType) : theOperation(LCB_SET), theType(aType), theExpTime(0) { }
406+ PutOptions(lcb_storage_type_t aType) : theOperation(LCB_SET), theType(aType), theExpTime(0), theWaitType(CB_WAIT_FALSE), theIsWaiting(false) { }
407
408 void setOptions(Item& aOptions);
409
410@@ -160,6 +172,12 @@
411 unsigned int getExmpTime() { return theExpTime; }
412
413 String getEncoding() { return theEncoding; }
414+
415+ cb_wait_type_t getWaitType() { return theWaitType; }
416+
417+ bool isWaiting() { return theIsWaiting; }
418+
419+ void setWaiting(bool isWaiting) { theIsWaiting = isWaiting; }
420 };
421
422 class ViewItemSequence : public ItemSequence
423@@ -299,6 +317,14 @@
424 static void
425 put (lcb_t aInstance, Iterator_t aKeys, Iterator_t aValues, PutOptions aOptions);
426
427+
428+ static void
429+ observe_callback(
430+ lcb_t instance,
431+ const void *cookie,
432+ lcb_error_t error,
433+ const lcb_observe_resp_t *resp);
434+
435 public:
436
437 CouchbaseFunction(const CouchbaseModule* module);
438@@ -560,6 +586,25 @@
439 const zorba::DynamicContext*) const;
440 };
441
442+/*******************************************************************************
443+ ******************************************************************************/
444+
445+class DeleteViewFunction : public CouchbaseFunction
446+{
447+ public:
448+ DeleteViewFunction(const CouchbaseModule* aModule)
449+ : CouchbaseFunction(aModule) {}
450+
451+ virtual ~DeleteViewFunction(){}
452+
453+ virtual zorba::String
454+ getLocalName() const { return "delete-view"; }
455+
456+ virtual zorba::ItemSequence_t
457+ evaluate( const Arguments_t&,
458+ const zorba::StaticContext*,
459+ const zorba::DynamicContext*) const;
460+};
461 } /*namespace couchbase*/ } /*namespace zorba*/
462
463
464
465=== modified file 'test/Queries/couchbase_module/view.xq'
466--- test/Queries/couchbase_module/view.xq 2013-01-10 07:59:35 +0000
467+++ test/Queries/couchbase_module/view.xq 2013-01-17 22:52:18 +0000
468@@ -6,12 +6,16 @@
469 "password" : null,
470 "bucket" : "default"});
471
472-cb:put-text($instance, "view", '{ "view" : 1 }');
473-
474-variable $view-name := cb:create-view($instance, "test-view", "test", {"key":"doc.view"});
475-
476-variable $data := cb:view($instance, $view-name);
477+cb:remove($instance, "view");
478+cb:put-text($instance, "view", '{ "view" : 1 }', { "wait" : "persist" });
479+
480+variable $cb-document := "test-view";
481+variable $cb-view := "view";
482+variable $view-name := cb:create-view($instance, $cb-document, $cb-view, {"key":"doc.view"});
483+
484+variable $data := cb:view($instance, $view-name, {"stale" : "false"});
485+cb:delete-view($instance, $cb-document);
486 for $d in jn:members($data("rows"))
487-where $d("key") >0
488+where $d("key") > 0
489 return $d
490

Subscribers

People subscribed via source and target branches

to all changes: