1 /* check-sources:disable-copyright-check */
2 /*
3  * Timo use cases:
4  *
5  * 1) adding object without name, returns a unique 128bit(?) ID for it
6  * 2) adding object with name (path), overwriting existing value
7  * 3) adding object with name (path), failing if the object already exists
8  * 4) appending data to an existing object, failing if it doesn't already exist
9  * 5) appending data to an existing object, or automatically creating it if it
10  * doesn't already exist and adding the data 6) adding metadata to added objects
11  * (for named/unnamed objects) 7) getting object contents (and metadata) by ID
12  * 8) getting object contents (and metadata) by name
13  * 9) getting object contents only partially (e.g. first 1000 bytes)
14  * 10) getting object metadata without its contents
15  * 11) copying ID object with changed metadata (is the content duplicated in the
16  * storage?) 12) copying named object with changed metadata (is the content
17  * duplicated in the storage?)
18  */
19 
20 #include <droplet.h>
21 #include <droplet/async.h>
22 #include <assert.h>
23 #include <sys/param.h>
24 
25 #define DATA_LEN 10000
26 
27 #define FILE1 "u.1"
28 #define FILE2 "u.2"
29 #define FILE3 "u.3"
30 #define FILE4 "u.4"
31 
32 dpl_ctx_t* ctx = NULL;
33 dpl_task_pool_t* pool = NULL;
34 char* folder = NULL;
35 int folder_len;
36 char id1[DPL_SYSMD_ID_SIZE + 1];
37 char file1_path[MAXPATHLEN];
38 char file2_path[MAXPATHLEN];
39 char file3_path[MAXPATHLEN];
40 char file4_path[MAXPATHLEN];
41 
42 pthread_mutex_t prog_lock;
43 pthread_cond_t prog_cond;
44 
45 pthread_mutex_t list_lock;
46 pthread_cond_t list_cond;
47 int n_ok = 0;
48 
banner(char * str)49 void banner(char* str)
50 {
51   int i;
52   int len = strlen(str);
53 
54   for (i = 0; i < len + 4; i++) fprintf(stderr, "*");
55   fprintf(stderr, "\n* %s *\n", str);
56   for (i = 0; i < len + 4; i++) fprintf(stderr, "*");
57   fprintf(stderr, "\n");
58 }
59 
free_all()60 void free_all()
61 {
62   banner("finished");
63 
64   if (NULL != pool) {
65     // dpl_task_pool_cancel(pool);
66     // dpl_task_pool_destroy(pool);
67   }
68 
69   dpl_ctx_free(ctx);  // free context
70 
71   dpl_free();  // free droplet library
72 
73   pthread_cond_signal(&prog_cond);
74 }
75 
cb_copy_named_object_with_new_md(void * handle)76 void cb_copy_named_object_with_new_md(void* handle)
77 {
78   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
79 
80   if (DPL_SUCCESS != atask->ret) {
81     fprintf(stderr, "rename object failed: %s (%d)\n",
82             dpl_status_str(atask->ret), atask->ret);
83     exit(1);
84   }
85 
86   dpl_async_task_free(atask);
87 
88   free_all();
89 }
90 
copy_named_object_with_new_md()91 void copy_named_object_with_new_md()
92 {
93   dpl_async_task_t* atask = NULL;
94   dpl_buf_t* buf = NULL;
95   dpl_status_t ret;
96   dpl_dict_t* metadata = NULL;
97 
98   banner("12 - copy named object with new metadata");
99 
100   metadata = dpl_dict_new(13);
101   if (NULL == metadata) {
102     ret = DPL_ENOMEM;
103     exit(1);
104   }
105 
106   ret = dpl_dict_add(metadata, "qux", "baz", 0);
107   if (DPL_SUCCESS != ret) {
108     fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret),
109             ret);
110     exit(1);
111   }
112 
113   atask = (dpl_async_task_t*)dpl_copy_async_prepare(
114       ctx,
115       NULL,                     // no src bucket
116       file1_path,               // the src resource
117       NULL,                     // no dst bucket
118       file4_path,               // dst resource
119       NULL,                     // no option
120       DPL_FTYPE_REG,            // regular file
121       DPL_COPY_DIRECTIVE_COPY,  // rename
122       metadata,                 // metadata
123       NULL,                     // no sysmd
124       NULL);                    // no server side condition
125 
126   if (NULL == atask) {
127     fprintf(stderr, "error preparing task\n");
128     exit(1);
129   }
130 
131   atask->cb_func = cb_copy_named_object_with_new_md;
132   atask->cb_arg = atask;
133 
134   dpl_task_pool_put(pool, (dpl_task_t*)atask);
135 }
136 
cb_copy_nameless_object_with_new_md(void * handle)137 void cb_copy_nameless_object_with_new_md(void* handle)
138 {
139   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
140 
141   if (DPL_SUCCESS != atask->ret) {
142     fprintf(stderr, "rename object failed: %s (%d)\n",
143             dpl_status_str(atask->ret), atask->ret);
144     exit(1);
145   }
146 
147   dpl_async_task_free(atask);
148 
149   copy_named_object_with_new_md();
150 }
151 
copy_nameless_object_with_new_md()152 void copy_nameless_object_with_new_md()
153 {
154   dpl_async_task_t* atask = NULL;
155   dpl_buf_t* buf = NULL;
156   dpl_status_t ret;
157   dpl_dict_t* metadata = NULL;
158 
159   banner("11 - copy nameless object with new metadata");
160 
161   metadata = dpl_dict_new(13);
162   if (NULL == metadata) {
163     ret = DPL_ENOMEM;
164     exit(1);
165   }
166 
167   ret = dpl_dict_add(metadata, "bar", "qux", 0);
168   if (DPL_SUCCESS != ret) {
169     fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret),
170             ret);
171     exit(1);
172   }
173 
174   /*
175    * note: With Dewpoint, it would be possible to copy nameless object into
176    * another nameless object. Does it make sense ? for now we copy it into a
177    * named object
178    */
179   atask = (dpl_async_task_t*)dpl_copy_id_async_prepare(
180       ctx,
181       NULL,                     // no src bucket
182       id1,                      // the src resource
183       NULL,                     // no dst bucket
184       file1_path,               // dst resource
185       NULL,                     // no option
186       DPL_FTYPE_REG,            // regular file
187       DPL_COPY_DIRECTIVE_COPY,  // rename
188       metadata,                 // metadata
189       NULL,                     // no sysmd
190       NULL);                    // no server side condition
191 
192   if (NULL == atask) {
193     fprintf(stderr, "error preparing task\n");
194     exit(1);
195   }
196 
197   atask->cb_func = cb_copy_nameless_object_with_new_md;
198   atask->cb_arg = atask;
199 
200   dpl_task_pool_put(pool, (dpl_task_t*)atask);
201 }
202 
cb_get_object_meta(void * handle)203 void cb_get_object_meta(void* handle)
204 {
205   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
206   int i;
207   dpl_dict_var_t* metadatum = NULL;
208 
209   if (DPL_SUCCESS != atask->ret) {
210     fprintf(stderr, "dpl_get failed: %s (%d)\n", dpl_status_str(atask->ret),
211             atask->ret);
212     exit(1);
213   }
214 
215   printf("metadata:\n");
216   dpl_dict_print(atask->u.head.metadata, stdout, 0);
217 
218   dpl_async_task_free(atask);
219 
220   copy_nameless_object_with_new_md();
221 }
222 
get_object_meta()223 void get_object_meta()
224 {
225   dpl_async_task_t* atask = NULL;
226   dpl_buf_t* buf = NULL;
227   dpl_status_t ret;
228 
229   banner("10 - get object meta");
230 
231   atask
232       = (dpl_async_task_t*)dpl_head_async_prepare(ctx,            // the context
233                                                   NULL,           // no bucket
234                                                   file3_path,     // the key
235                                                   NULL,           // no opion
236                                                   DPL_FTYPE_REG,  // object type
237                                                   NULL);  // no condition
238 
239   if (NULL == atask) {
240     fprintf(stderr, "error preparing task\n");
241     exit(1);
242   }
243 
244   atask->cb_func = cb_get_object_meta;
245   atask->cb_arg = atask;
246 
247   dpl_task_pool_put(pool, (dpl_task_t*)atask);
248 }
249 
cb_get_named_object_partially(void * handle)250 void cb_get_named_object_partially(void* handle)
251 {
252   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
253   int i;
254   dpl_dict_var_t* metadatum = NULL;
255 
256   if (DPL_SUCCESS != atask->ret) {
257     fprintf(stderr, "dpl_get failed: %s (%d)\n", dpl_status_str(atask->ret),
258             atask->ret);
259     exit(1);
260   }
261 
262   printf("data len: %d\n", dpl_buf_size(atask->u.get.buf));
263   printf("metadata:\n");
264   dpl_dict_print(atask->u.get.metadata, stdout, 0);
265 
266   dpl_async_task_free(atask);
267 
268   get_object_meta();
269 }
270 
get_named_object_partially()271 void get_named_object_partially()
272 {
273   dpl_async_task_t* atask = NULL;
274   dpl_buf_t* buf = NULL;
275   dpl_status_t ret;
276   dpl_range_t range;
277 
278   banner("9 - get named object partially");
279 
280   // first 1000 bytes
281   range.start = 0;
282   range.end = 999;
283   atask
284       = (dpl_async_task_t*)dpl_get_async_prepare(ctx,            // the context
285                                                  NULL,           // no bucket
286                                                  file3_path,     // the key
287                                                  NULL,           // no option
288                                                  DPL_FTYPE_REG,  // object type
289                                                  NULL,           // no condition
290                                                  &range);        // range
291 
292   if (NULL == atask) {
293     fprintf(stderr, "error preparing task\n");
294     exit(1);
295   }
296 
297   atask->cb_func = cb_get_named_object_partially;
298   atask->cb_arg = atask;
299 
300   dpl_task_pool_put(pool, (dpl_task_t*)atask);
301 }
302 
cb_get_named_object(void * handle)303 void cb_get_named_object(void* handle)
304 {
305   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
306   int i;
307   dpl_dict_var_t* metadatum = NULL;
308 
309   if (DPL_SUCCESS != atask->ret) {
310     fprintf(stderr, "dpl_get failed: %s (%d)\n", dpl_status_str(atask->ret),
311             atask->ret);
312     exit(1);
313   }
314 
315   printf("data:\n");
316   write(1, dpl_buf_ptr(atask->u.get.buf),
317         MIN(dpl_buf_size(atask->u.get.buf), 10));
318   printf("...\nmetadata:\n");
319   dpl_dict_print(atask->u.get.metadata, stdout, 0);
320 
321   dpl_async_task_free(atask);
322 
323   get_named_object_partially();
324 }
325 
get_named_object()326 void get_named_object()
327 {
328   dpl_async_task_t* atask = NULL;
329   dpl_buf_t* buf = NULL;
330   dpl_status_t ret;
331 
332   banner("8 - get named object data+metadata");
333 
334   atask
335       = (dpl_async_task_t*)dpl_get_async_prepare(ctx,            // the context
336                                                  NULL,           // no bucket
337                                                  file3_path,     // the key
338                                                  NULL,           // no opion
339                                                  DPL_FTYPE_REG,  // object type
340                                                  NULL,           // no condition
341                                                  NULL);          // no range
342 
343   if (NULL == atask) {
344     fprintf(stderr, "error preparing task\n");
345     exit(1);
346   }
347 
348   atask->cb_func = cb_get_named_object;
349   atask->cb_arg = atask;
350 
351   dpl_task_pool_put(pool, (dpl_task_t*)atask);
352 }
353 
cb_get_nameless_object(void * handle)354 void cb_get_nameless_object(void* handle)
355 {
356   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
357   int i;
358   dpl_dict_var_t* metadatum = NULL;
359 
360   if (DPL_SUCCESS != atask->ret) {
361     fprintf(stderr, "dpl_get failed: %s (%d)\n", dpl_status_str(atask->ret),
362             atask->ret);
363     exit(1);
364   }
365 
366   printf("data:\n");
367   write(1, dpl_buf_ptr(atask->u.get.buf),
368         MIN(dpl_buf_size(atask->u.get.buf), 10));
369   printf("...\nmetadata:\n");
370   dpl_dict_print(atask->u.get.metadata, stdout, 0);
371 
372   dpl_async_task_free(atask);
373 
374   get_named_object();
375 }
376 
get_nameless_object()377 void get_nameless_object()
378 {
379   dpl_async_task_t* atask = NULL;
380   dpl_buf_t* buf = NULL;
381   dpl_status_t ret;
382 
383   banner("7 - get nameless object data+metadata");
384 
385   atask = (dpl_async_task_t*)dpl_get_id_async_prepare(
386       ctx,            // the context
387       NULL,           // no bucket
388       id1,            // the key
389       NULL,           // no opion
390       DPL_FTYPE_REG,  // object type
391       NULL,           // no condition
392       NULL);          // no range
393 
394   if (NULL == atask) {
395     fprintf(stderr, "error preparing task\n");
396     exit(1);
397   }
398 
399   atask->cb_func = cb_get_nameless_object;
400   atask->cb_arg = atask;
401 
402   dpl_task_pool_put(pool, (dpl_task_t*)atask);
403 }
404 
cb_update_metadata_nameless_object(void * handle)405 void cb_update_metadata_nameless_object(void* handle)
406 {
407   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
408 
409   if (DPL_SUCCESS != atask->ret) {
410     fprintf(stderr, "abnormal answer: %s (%d)\n", dpl_status_str(atask->ret),
411             atask->ret);
412     exit(1);
413   }
414 
415   dpl_async_task_free(atask);
416 
417   get_nameless_object();
418 }
419 
update_metadata_nameless_object()420 void update_metadata_nameless_object()
421 {
422   dpl_async_task_t* atask = NULL;
423   dpl_status_t ret;
424   dpl_option_t option;
425   dpl_dict_t* metadata = NULL;
426 
427   banner("6bis - append metadata to existing nameless object");
428 
429   metadata = dpl_dict_new(13);
430   if (NULL == metadata) {
431     ret = DPL_ENOMEM;
432     exit(1);
433   }
434 
435   ret = dpl_dict_add(metadata, "foo", "bar", 0);
436   if (DPL_SUCCESS != ret) {
437     fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret),
438             ret);
439     exit(1);
440   }
441 
442   option.mask = DPL_OPTION_APPEND_METADATA;
443 
444   atask = (dpl_async_task_t*)dpl_put_id_async_prepare(
445       ctx,
446       NULL,           // no bucket
447       id1,            // the id
448       &option,        // option
449       DPL_FTYPE_REG,  // regular object
450       NULL,           // condition
451       NULL,           // range
452       metadata,       // the metadata
453       NULL,           // no sysmd
454       NULL);          // object body
455 
456   dpl_dict_free(metadata);
457 
458   if (NULL == atask) {
459     fprintf(stderr, "error preparing task\n");
460     exit(1);
461   }
462 
463   atask->cb_func = cb_update_metadata_nameless_object;
464   atask->cb_arg = atask;
465 
466   dpl_task_pool_put(pool, (dpl_task_t*)atask);
467 }
468 
cb_update_metadata_named_object(void * handle)469 void cb_update_metadata_named_object(void* handle)
470 {
471   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
472 
473   if (DPL_SUCCESS != atask->ret) {
474     fprintf(stderr, "abnormal answer: %s (%d)\n", dpl_status_str(atask->ret),
475             atask->ret);
476     exit(1);
477   }
478 
479   dpl_async_task_free(atask);
480 
481   update_metadata_nameless_object();
482 }
483 
update_metadata_named_object()484 void update_metadata_named_object()
485 {
486   dpl_async_task_t* atask = NULL;
487   dpl_status_t ret;
488   dpl_option_t option;
489   dpl_dict_t* metadata = NULL;
490 
491   banner("6 - append metadata to existing named object");
492 
493   metadata = dpl_dict_new(13);
494   if (NULL == metadata) {
495     ret = DPL_ENOMEM;
496     exit(1);
497   }
498 
499   ret = dpl_dict_add(metadata, "foo", "bar", 0);
500   if (DPL_SUCCESS != ret) {
501     fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret),
502             ret);
503     exit(1);
504   }
505 
506   option.mask = DPL_OPTION_APPEND_METADATA;
507 
508   atask = (dpl_async_task_t*)dpl_put_async_prepare(
509       ctx,
510       NULL,           // no bucket
511       file3_path,     // the id
512       &option,        // option
513       DPL_FTYPE_REG,  // regular object
514       NULL,           // condition
515       NULL,           // range
516       metadata,       // the metadata
517       NULL,           // no sysmd
518       NULL);          // object body
519 
520   dpl_dict_free(metadata);
521 
522   if (NULL == atask) {
523     fprintf(stderr, "error preparing task\n");
524     exit(1);
525   }
526 
527   atask->cb_func = cb_update_metadata_named_object;
528   atask->cb_arg = atask;
529 
530   dpl_task_pool_put(pool, (dpl_task_t*)atask);
531 }
532 
cb_append_to_nonexisting_named_object(void * handle)533 void cb_append_to_nonexisting_named_object(void* handle)
534 {
535   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
536 
537   if (DPL_SUCCESS != atask->ret) {
538     fprintf(stderr, "abnormal answer: %s (%d)\n", dpl_status_str(atask->ret),
539             atask->ret);
540     exit(1);
541   }
542 
543   dpl_async_task_free(atask);
544 
545   update_metadata_named_object();
546 }
547 
append_to_nonexisting_named_object()548 void append_to_nonexisting_named_object()
549 {
550   dpl_async_task_t* atask = NULL;
551   dpl_buf_t* buf = NULL;
552   dpl_status_t ret;
553 
554   buf = dpl_buf_new();
555   if (NULL == buf) exit(1);
556 
557   buf->size = DATA_LEN;
558   buf->ptr = malloc(buf->size);
559   if (NULL == buf->ptr) {
560     fprintf(stderr, "alloc data failed\n");
561     exit(1);
562   }
563 
564   memset(buf->ptr, 'z', buf->size);
565 
566   banner("5 - append data to nonexisting named object");
567 
568   atask = (dpl_async_task_t*)dpl_post_async_prepare(
569       ctx,
570       NULL,           // no bucket
571       file3_path,     // the id
572       NULL,           // option
573       DPL_FTYPE_REG,  // regular object
574       NULL,           // no condition
575       NULL,           // range
576       NULL,           // the metadata
577       NULL,           // no sysmd
578       buf,            // object body
579       NULL);          // query params
580   if (NULL == atask) {
581     fprintf(stderr, "error preparing task\n");
582     exit(1);
583   }
584 
585   atask->cb_func = cb_append_to_nonexisting_named_object;
586   atask->cb_arg = atask;
587 
588   dpl_task_pool_put(pool, (dpl_task_t*)atask);
589 }
590 
cb_append_to_nonexisting_named_object_precond(void * handle)591 void cb_append_to_nonexisting_named_object_precond(void* handle)
592 {
593   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
594 
595   if (DPL_EPRECOND != atask->ret) {
596     fprintf(stderr, "abnormal answer: %s (%d)\n", dpl_status_str(atask->ret),
597             atask->ret);
598     // exit(1);
599   }
600 
601   dpl_async_task_free(atask);
602 
603   append_to_nonexisting_named_object();
604 }
605 
append_to_nonexisting_named_object_precond()606 void append_to_nonexisting_named_object_precond()
607 {
608   dpl_async_task_t* atask = NULL;
609   dpl_buf_t* buf = NULL;
610   dpl_status_t ret;
611   dpl_condition_t condition;
612 
613   buf = dpl_buf_new();
614   if (NULL == buf) exit(1);
615 
616   buf->size = DATA_LEN;
617   buf->ptr = malloc(buf->size);
618   if (NULL == buf->ptr) {
619     fprintf(stderr, "alloc data failed\n");
620     exit(1);
621   }
622 
623   memset(buf->ptr, 'z', buf->size);
624 
625   banner("4 - append data to nonexisting named object with precondition");
626 
627   condition.conds[0].type = DPL_CONDITION_IF_MATCH;
628   condition.conds[0].etag[0] = '*';
629   condition.conds[0].etag[1] = 0;
630   condition.n_conds = 1;
631 
632   atask = (dpl_async_task_t*)dpl_post_async_prepare(
633       ctx,
634       NULL,           // no bucket
635       file3_path,     // the id
636       NULL,           // option
637       DPL_FTYPE_REG,  // regular object
638       &condition,     // expect failure if exists
639       NULL,           // range
640       NULL,           // the metadata
641       NULL,           // no sysmd
642       buf,            // object body
643       NULL);          // query params
644   if (NULL == atask) {
645     fprintf(stderr, "error preparing task\n");
646     exit(1);
647   }
648 
649   atask->cb_func = cb_append_to_nonexisting_named_object_precond;
650   atask->cb_arg = atask;
651 
652   dpl_task_pool_put(pool, (dpl_task_t*)atask);
653 }
654 
cb_add_existing_named_object(void * handle)655 void cb_add_existing_named_object(void* handle)
656 {
657   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
658 
659   if (DPL_EPRECOND != atask->ret) {
660     fprintf(stderr, "abnormal answer: %s (%d)\n", dpl_status_str(atask->ret),
661             atask->ret);
662     exit(1);
663   }
664 
665   dpl_async_task_free(atask);
666 
667   append_to_nonexisting_named_object_precond();
668 }
669 
add_existing_named_object()670 void add_existing_named_object()
671 {
672   dpl_async_task_t* atask = NULL;
673   dpl_buf_t* buf = NULL;
674   dpl_status_t ret;
675   dpl_condition_t condition;
676 
677   buf = dpl_buf_new();
678   if (NULL == buf) exit(1);
679 
680   buf->size = DATA_LEN;
681   buf->ptr = malloc(buf->size);
682   if (NULL == buf->ptr) {
683     fprintf(stderr, "alloc data failed\n");
684     exit(1);
685   }
686 
687   memset(buf->ptr, 'y', buf->size);
688 
689   banner("3 - add existing named object with precondition");
690 
691   condition.conds[0].type = DPL_CONDITION_IF_NONE_MATCH;
692   condition.conds[0].etag[0] = '*';
693   condition.conds[0].etag[1] = 0;
694   condition.n_conds = 1;
695 
696   atask = (dpl_async_task_t*)dpl_put_async_prepare(
697       ctx,
698       NULL,           // no bucket
699       file2_path,     // the id
700       NULL,           // no option
701       DPL_FTYPE_REG,  // regular object
702       &condition,     // expect failure if exists
703       NULL,           // no range
704       NULL,           // the metadata
705       NULL,           // no sysmd
706       buf);           // object body
707   if (NULL == atask) {
708     fprintf(stderr, "error preparing task\n");
709     exit(1);
710   }
711 
712   atask->cb_func = cb_add_existing_named_object;
713   atask->cb_arg = atask;
714 
715   dpl_task_pool_put(pool, (dpl_task_t*)atask);
716 }
717 
cb_add_existing_named_object_no_precond(void * handle)718 void cb_add_existing_named_object_no_precond(void* handle)
719 {
720   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
721 
722   if (DPL_EPRECOND != atask->ret) {
723     fprintf(stderr, "abnormal answer: %s (%d)\n", dpl_status_str(atask->ret),
724             atask->ret);
725     exit(1);
726   }
727 
728   dpl_async_task_free(atask);
729 
730   add_existing_named_object();
731 }
732 
add_existing_named_object_no_precond()733 void add_existing_named_object_no_precond()
734 {
735   dpl_async_task_t* atask = NULL;
736   dpl_buf_t* buf = NULL;
737   dpl_status_t ret;
738 
739   buf = dpl_buf_new();
740   if (NULL == buf) exit(1);
741 
742   buf->size = DATA_LEN;
743   buf->ptr = malloc(buf->size);
744   if (NULL == buf->ptr) {
745     fprintf(stderr, "alloc data failed\n");
746     exit(1);
747   }
748 
749   memset(buf->ptr, 'y', buf->size);
750 
751   banner("2bis - add existing named object");
752 
753   atask = (dpl_async_task_t*)dpl_put_async_prepare(
754       ctx,
755       NULL,           // no bucket
756       file2_path,     // the id
757       NULL,           // no option
758       DPL_FTYPE_REG,  // regular object
759       NULL,           // no condition
760       NULL,           // no range
761       NULL,           // the metadata
762       NULL,           // no sysmd
763       buf);           // object body
764   if (NULL == atask) {
765     fprintf(stderr, "error preparing task\n");
766     exit(1);
767   }
768 
769   atask->cb_func = cb_add_existing_named_object;
770   atask->cb_arg = atask;
771 
772   dpl_task_pool_put(pool, (dpl_task_t*)atask);
773 }
774 
cb_add_nonexisting_named_object(void * handle)775 void cb_add_nonexisting_named_object(void* handle)
776 {
777   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
778 
779   if (DPL_SUCCESS != atask->ret) {
780     fprintf(stderr, "add named object failed: %s (%d)\n",
781             dpl_status_str(atask->ret), atask->ret);
782     exit(1);
783   }
784 
785   dpl_async_task_free(atask);
786 
787   add_existing_named_object();
788 }
789 
add_nonexisting_named_object()790 void add_nonexisting_named_object()
791 {
792   dpl_async_task_t* atask = NULL;
793   dpl_buf_t* buf = NULL;
794   dpl_status_t ret;
795 
796   buf = dpl_buf_new();
797   if (NULL == buf) exit(1);
798 
799   buf->size = DATA_LEN;
800   buf->ptr = malloc(buf->size);
801   if (NULL == buf->ptr) {
802     fprintf(stderr, "alloc data failed\n");
803     exit(1);
804   }
805 
806   memset(buf->ptr, 'y', buf->size);
807 
808   banner("2 - add nonexisting named object");
809 
810   atask = (dpl_async_task_t*)dpl_put_async_prepare(
811       ctx,
812       NULL,           // no bucket
813       file2_path,     // the id
814       NULL,           // no option
815       DPL_FTYPE_REG,  // regular object
816       NULL,           // no condition
817       NULL,           // no range
818       NULL,           // the metadata
819       NULL,           // no sysmd
820       buf);           // object body
821   if (NULL == atask) {
822     fprintf(stderr, "error preparing task\n");
823     exit(1);
824   }
825 
826   atask->cb_func = cb_add_nonexisting_named_object;
827   atask->cb_arg = atask;
828 
829   dpl_task_pool_put(pool, (dpl_task_t*)atask);
830 }
831 
cb_add_nameless_object(void * handle)832 void cb_add_nameless_object(void* handle)
833 {
834   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
835 
836   if (DPL_SUCCESS != atask->ret) {
837     fprintf(stderr, "add object failed: %s (%d)\n", dpl_status_str(atask->ret),
838             atask->ret);
839     exit(1);
840   }
841 
842   fprintf(stderr, "id=%s path=%s\n", atask->u.post.sysmd_returned.id,
843           atask->u.post.sysmd_returned.path);
844 
845   strcpy(id1, atask->u.post.sysmd_returned.id);
846 
847   dpl_async_task_free(atask);
848 
849   add_nonexisting_named_object();
850 }
851 
add_nameless_object()852 void add_nameless_object()
853 {
854   dpl_async_task_t* atask = NULL;
855   dpl_buf_t* buf = NULL;
856   dpl_status_t ret;
857 
858   buf = dpl_buf_new();
859   if (NULL == buf) exit(1);
860 
861   buf->size = DATA_LEN;
862   buf->ptr = malloc(buf->size);
863   if (NULL == buf->ptr) {
864     fprintf(stderr, "alloc data failed\n");
865     exit(1);
866   }
867 
868   memset(buf->ptr, 'x', buf->size);
869 
870   banner("1 - add nameless object");
871 
872   atask = (dpl_async_task_t*)dpl_post_id_async_prepare(
873       ctx,            // the context
874       NULL,           // no bucket
875       NULL,           // no id
876       NULL,           // no option
877       DPL_FTYPE_REG,  // regular object
878       NULL,           // condition
879       NULL,           // range
880       NULL,           // the metadata
881       NULL,           // no sysmd
882       buf,            // object body
883       NULL);          // no query params
884   if (NULL == atask) {
885     fprintf(stderr, "error preparing task\n");
886     exit(1);
887   }
888 
889   atask->cb_func = cb_add_nameless_object;
890   atask->cb_arg = atask;
891 
892   dpl_task_pool_put(pool, (dpl_task_t*)atask);
893 }
894 
cb_make_folder(void * handle)895 void cb_make_folder(void* handle)
896 {
897   dpl_async_task_t* atask = (dpl_async_task_t*)handle;
898 
899   if (DPL_SUCCESS != atask->ret) {
900     fprintf(stderr, "make dir failed: %s (%d)\n", dpl_status_str(atask->ret),
901             atask->ret);
902     exit(1);
903   }
904 
905   dpl_async_task_free(atask);
906 
907   add_nameless_object();
908 }
909 
make_folder()910 void make_folder()
911 {
912   dpl_status_t ret, ret2;
913   dpl_async_task_t* atask = NULL;
914   dpl_buf_t* buf = NULL;
915 
916   banner("creating folder");
917 
918   buf = dpl_buf_new();
919   if (NULL == buf) exit(1);
920 
921   atask = (dpl_async_task_t*)dpl_put_async_prepare(ctx,     // the context
922                                                    NULL,    // no bucket
923                                                    folder,  // the folder
924                                                    NULL,    // no option
925                                                    DPL_FTYPE_DIR,  // directory
926                                                    NULL,  // no condition
927                                                    NULL,  // no range
928                                                    NULL,  // no metadata
929                                                    NULL,  // no sysmd
930                                                    buf);  // object body
931   if (NULL == atask) {
932     fprintf(stderr, "error preparing task\n");
933     exit(1);
934   }
935 
936   atask->cb_func = cb_make_folder;
937   atask->cb_arg = atask;
938 
939   dpl_task_pool_put(pool, (dpl_task_t*)atask);
940 }
941 
main(int argc,char ** argv)942 int main(int argc, char** argv)
943 {
944   int ret;
945 
946   if (2 != argc) {
947     fprintf(stderr, "usage: restrest folder\n");
948     exit(1);
949   }
950 
951   folder = argv[1];
952   if (folder[0] == '/') {
953     fprintf(stderr, "folder name must not start with slash");
954     exit(1);
955   }
956 
957   folder_len = strlen(folder);
958   if (folder_len < 1) {
959     fprintf(stderr, "bad folder\n");
960     exit(1);
961   }
962   if (folder[folder_len - 1] != '/') {
963     fprintf(stderr, "folder name must end with a slash\n");
964     exit(1);
965   }
966 
967   snprintf(file1_path, sizeof(file1_path), "%s%s", folder, FILE1);
968   snprintf(file2_path, sizeof(file2_path), "%s%s", folder, FILE2);
969   snprintf(file3_path, sizeof(file3_path), "%s%s", folder, FILE3);
970   snprintf(file4_path, sizeof(file4_path), "%s%s", folder, FILE4);
971 
972   ret = dpl_init();  // init droplet library
973   if (DPL_SUCCESS != ret) {
974     fprintf(stderr, "dpl_init failed\n");
975     exit(1);
976   }
977 
978   // open default profile
979   ctx = dpl_ctx_new(NULL,   // droplet directory, default: "~/.droplet"
980                     NULL);  // droplet profile, default:   "default"
981   if (NULL == ctx) {
982     fprintf(stderr, "dpl_ctx_new failed\n");
983     ret = 1;
984   }
985 
986   // ctx->trace_level = ~0;
987   // ctx->trace_buffers = 1;
988 
989   pool = dpl_task_pool_create(ctx, "resttest", 10);
990   if (NULL == pool) {
991     fprintf(stderr, "error creating pool\n");
992     exit(1);
993   }
994 
995   /**/
996 
997   pthread_mutex_init(&prog_lock, NULL);
998   pthread_cond_init(&prog_cond, NULL);
999 
1000   make_folder();
1001 
1002   pthread_cond_wait(&prog_cond, &prog_lock);
1003 
1004   return 0;
1005 }
1006