summaryrefslogtreecommitdiff
path: root/src/lib/eio
diff options
context:
space:
mode:
authorCedric Bail <cedric@osg.samsung.com>2016-07-31 21:41:05 -0700
committerCedric BAIL <cedric@osg.samsung.com>2016-09-08 15:16:23 -0700
commit52c63190d5b9906698b5e1872ce6448185218d91 (patch)
treefaf2eb6cb76cd1f3006e09502f568a7c46544119 /src/lib/eio
parentf17f389b66c734571e85d1b008dfd43fc7d40b28 (diff)
eio: rework efl_io_manager to use efl_future.
Diffstat (limited to 'src/lib/eio')
-rw-r--r--src/lib/eio/efl_io_manager.c758
-rw-r--r--src/lib/eio/efl_io_manager.eo105
2 files changed, 383 insertions, 480 deletions
diff --git a/src/lib/eio/efl_io_manager.c b/src/lib/eio/efl_io_manager.c
index 81514f52c9..c3c08095e9 100644
--- a/src/lib/eio/efl_io_manager.c
+++ b/src/lib/eio/efl_io_manager.c
@@ -22,10 +22,12 @@
22# include <config.h> 22# include <config.h>
23#endif 23#endif
24 24
25
26#include <Eo.h> 25#include <Eo.h>
26#include <Ecore.h>
27#include "Eio.h" 27#include "Eio.h"
28 28
29#include "eio_private.h"
30
29typedef struct _Efl_Io_Manager_Data Efl_Io_Manager_Data; 31typedef struct _Efl_Io_Manager_Data Efl_Io_Manager_Data;
30 32
31struct _Efl_Io_Manager_Data 33struct _Efl_Io_Manager_Data
@@ -50,389 +52,364 @@ struct _Job_Closure
50 52
51/* Helper functions */ 53/* Helper functions */
52 54
53static Job_Closure * 55static void
54_job_closure_create(Eo *obj, Efl_Io_Manager_Data *pdata, Eina_Promise_Owner *owner) 56_no_future(void *data, const Efl_Event *ev EINA_UNUSED)
55{ 57{
56 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); 58 Eio_File *h = data;
57 EINA_SAFETY_ON_NULL_RETURN_VAL(pdata, NULL);
58 EINA_SAFETY_ON_NULL_RETURN_VAL(owner, NULL);
59
60 Job_Closure *closure = malloc(sizeof(Job_Closure));
61
62 if (!closure)
63 {
64 EINA_LOG_CRIT("Failed to allocate memory.");
65 return 0;
66 }
67
68 closure->object = efl_ref(obj);
69 closure->pdata = pdata;
70 closure->promise = owner;
71 closure->file = NULL; // Will be set once the Eio operation is under way
72 closure->delete_me = EINA_FALSE;
73 closure->delayed_arg = NULL;
74 closure->direct_func = NULL;
75
76 pdata->operations = eina_list_prepend(pdata->operations, closure);
77 59
78 return closure; 60 eio_file_cancel(h);
79} 61}
80 62
81static void 63static void
82_job_closure_del(Job_Closure *closure) 64_forced_shutdown(void *data, const Efl_Event *ev EINA_UNUSED)
83{ 65{
84 EINA_SAFETY_ON_NULL_RETURN(closure); 66 Eio_File *h = data;
85 Efl_Io_Manager_Data *pdata = closure->pdata;
86 if (pdata)
87 pdata->operations = eina_list_remove(pdata->operations, closure);
88 67
89 efl_unref(closure->object); 68 eio_file_cancel(h);
90 69 // FIXME: handle memory lock here !
91 if (closure->delayed_arg) 70 // Acceptable strategy will be to unlock all thread as
92 free(closure->delayed_arg); 71 // if we were freeing some memory
93 72 // FIXME: Handle long to finish thread
94 free(closure); 73 ecore_thread_wait(h->thread, 1.0);
95} 74}
96 75
97static void 76static void
98_file_error_cb(void *data, Eio_File *handler EINA_UNUSED, int error) 77_progress(void *data EINA_UNUSED, const Efl_Event *ev)
99{ 78{
100 Job_Closure *operation = data; 79 efl_key_data_set(ev->object, "_eio.progress", (void*) EINA_TRUE);
101
102 EINA_SAFETY_ON_NULL_RETURN(operation);
103 EINA_SAFETY_ON_NULL_RETURN(operation->promise);
104
105 eina_promise_owner_error_set(operation->promise, error);
106
107 _job_closure_del(operation);
108} 80}
109 81
110/* Basic listing callbacks */ 82EFL_CALLBACKS_ARRAY_DEFINE(promise_progress_handling,
111 83 { EFL_PROMISE_EVENT_FUTURE_PROGRESS_SET, _progress },
112static Eina_Bool 84 { EFL_PROMISE_EVENT_FUTURE_NONE, _no_future },
113_file_ls_filter_cb_helper(const Efl_Event_Description *event, void *data, const char *file) 85 { EFL_EVENT_DEL, _forced_shutdown });
114{
115 Job_Closure *operation = data;
116
117 EINA_SAFETY_ON_NULL_RETURN_VAL(operation, EINA_FALSE);
118 EINA_SAFETY_ON_NULL_RETURN_VAL(operation->pdata, EINA_FALSE);
119 86
120 Eio_Filter_Name_Data* event_info = malloc(sizeof(Eio_Filter_Name_Data)); 87EFL_CALLBACKS_ARRAY_DEFINE(promise_handling,
88 { EFL_PROMISE_EVENT_FUTURE_NONE, _no_future },
89 { EFL_EVENT_DEL, _forced_shutdown });
121 90
122 EINA_SAFETY_ON_NULL_RETURN_VAL(event_info, EINA_FALSE); 91static void
123 92_file_done_data_cb(void *data, Eio_File *handler, const char *attr_data, unsigned int size)
124 event_info->file = file; 93{
125 event_info->filter = EINA_FALSE; 94 Efl_Promise *p = data;
95 Eina_Binbuf *buf;
126 96
127 efl_event_callback_legacy_call(operation->pdata->object, event, event_info); 97 efl_event_callback_array_del(p, promise_handling(), handler);
128 98
129 Eina_Bool filter = event_info->filter; 99 buf = eina_binbuf_new();
100 eina_binbuf_append_length(buf, (const unsigned char*) attr_data, size);
130 101
131 free(event_info); 102 efl_promise_value_set(p, buf, EINA_FREE_CB(eina_binbuf_free));
132 103
133 return filter; 104 efl_del(p);
134} 105}
135 106
136static Eina_Bool 107static void
137_file_ls_filter_xattr_cb(void *data, Eio_File *handler EINA_UNUSED, const char *file) 108_file_error_cb(void *data, Eio_File *handler, int error)
138{ 109{
139 return _file_ls_filter_cb_helper(EFL_IO_MANAGER_EVENT_XATTR, data, file); 110 Efl_Promise *p = data;
140}
141 111
142static Eina_Bool 112 efl_event_callback_array_del(p, promise_handling(), handler);
143_file_ls_filter_named_cb(void *data, Eio_File *handler EINA_UNUSED, const char *file)
144{
145 return _file_ls_filter_cb_helper(EFL_IO_MANAGER_EVENT_FILTER_NAME, data, file);
146}
147 113
148static void 114 efl_promise_failed(p, error);
149_file_ls_main_cb(void *data, Eio_File *handler EINA_UNUSED, const char *file)
150{
151 Job_Closure *operation = data;
152 EINA_SAFETY_ON_NULL_RETURN(operation);
153 EINA_SAFETY_ON_NULL_RETURN(operation->promise);
154 115
155 eina_promise_owner_progress(operation->promise, (void*)file); 116 efl_del(p);
156} 117}
157 118
158static void 119static void
159_file_done_cb(void *data, Eio_File *handler EINA_UNUSED) 120_file_done_cb(void *data, Eio_File *handler)
160{ 121{
161 Job_Closure *operation = data; 122 Efl_Promise *p = data;
162 123 uint64_t *v = calloc(1, sizeof (uint64_t));
163 EINA_SAFETY_ON_NULL_RETURN(operation);
164 EINA_SAFETY_ON_NULL_RETURN(operation->promise);
165 124
166 // Placeholder value. We just want the callback to be called. 125 efl_event_callback_array_del(p, promise_handling(), handler);
167 eina_promise_owner_value_set(operation->promise, NULL, NULL);
168 126
169 _job_closure_del(operation); 127 if (!v)
170} 128 {
129 efl_promise_failed(p, ENOMEM);
130 goto end;
131 }
171 132
172static void 133 *v = handler->length;
173_free_xattr_data(Eio_Xattr_Data *value) 134 efl_promise_value_set(p, v, free);
174{
175 EINA_SAFETY_ON_NULL_RETURN(value);
176 if (value->data)
177 free((void*)value->data);
178 135
179 free(value); 136 end:
137 efl_del(p);
180} 138}
181 139
140/* Basic listing callbacks */
182static void 141static void
183_file_done_data_cb(void *data, Eio_File *handler EINA_UNUSED, const char *attr_data, unsigned int size) 142_cleanup_string_progress(void *data)
184{ 143{
185 Job_Closure *operation = data; 144 Eina_Array *existing = data;
186 Eio_Xattr_Data *ret_data = NULL; 145 Eina_Stringshare *s;
187 146 Eina_Array_Iterator it;
188 EINA_SAFETY_ON_NULL_RETURN(operation); 147 unsigned int i;
189 EINA_SAFETY_ON_NULL_RETURN(operation->promise);
190 148
191 ret_data = calloc(sizeof(Eio_Xattr_Data), 1); 149 EINA_ARRAY_ITER_NEXT(existing, i, s, it)
192 ret_data->data = calloc(sizeof(char), size + 1); 150 eina_stringshare_del(s);
193 strcpy((char*)ret_data->data, attr_data); 151 eina_array_free(existing);
194 ret_data->size = size;
195
196 eina_promise_owner_value_set(operation->promise, ret_data, (Eina_Promise_Free_Cb)&_free_xattr_data);
197
198 _job_closure_del(operation);
199} 152}
200 153
201/* Direct listing callbacks */ 154static void
202 155_cleanup_info_progress(void *data)
203static Eina_Bool
204_file_direct_ls_filter_cb(void *data, Eio_File *handle EINA_UNUSED, const Eina_File_Direct_Info *info)
205{ 156{
206 Job_Closure *operation = data; 157 Eina_Array *existing = data;
207 158 Eio_File_Direct_Info *d; // This is a trick because we use the head of the structure
208 EINA_SAFETY_ON_NULL_RETURN_VAL(operation, EINA_FALSE); 159 Eina_Array_Iterator it;
209 EINA_SAFETY_ON_NULL_RETURN_VAL(operation->pdata, EINA_FALSE); 160 unsigned int i;
210 161
211 Eio_Filter_Direct_Data event_info; 162 EINA_ARRAY_ITER_NEXT(existing, i, d, it)
212 163 eio_direct_info_free(d);
213 event_info.info = info; 164 eina_array_free(existing);
214 event_info.filter = EINA_FALSE;
215
216 efl_event_callback_legacy_call(operation->pdata->object, EFL_IO_MANAGER_EVENT_FILTER_DIRECT, &event_info);
217
218 Eina_Bool filter = event_info.filter;
219
220 return filter;
221} 165}
222 166
223static void 167static void
224_file_direct_ls_main_cb(void *data, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info) 168_file_string_cb(void *data, Eio_File *handler, Eina_Array *gather)
225{ 169{
226 Job_Closure *operation = data; 170 Efl_Promise *p = data;
227 EINA_SAFETY_ON_NULL_RETURN(operation); 171 Eina_Array *existing = efl_key_data_get(p, "_eio.stored");
228 EINA_SAFETY_ON_NULL_RETURN(operation->promise); 172 void **tmp;
229 173
230 eina_promise_owner_progress(operation->promise, (void*)info); 174 // If a future is set, but without progress, we should assume
231} 175 // that we should discard all future progress. [[FIXME]]
176 if (existing)
177 {
178 tmp = realloc(existing->data, sizeof (void*) * (existing->count + gather->count));
179 if (!tmp)
180 {
181 eina_array_free(gather);
182 eina_array_free(existing);
183 efl_key_data_set(p, "_eio.stored", NULL);
184 handler->error = ENOMEM;
185 eio_file_cancel(handler);
186 return ;
187 }
188
189 existing->data = tmp;
190 memcpy(existing->data + existing->count, gather->data, gather->count * sizeof (void*));
191 existing->count += gather->count;
192 existing->total = existing->count;
193 eina_array_free(gather);
194 }
195 else
196 {
197 existing = gather;
198 }
232 199
233static void 200 if (!efl_key_data_get(p, "_eio.progress"))
234_ls_direct_notify_start(void* data, Eina_Promise_Owner *promise EINA_UNUSED) 201 {
235{ 202 efl_key_data_set(p, "_eio.stored", existing);
236 Job_Closure *operation_data = (Job_Closure*)data; 203 return ;
237 char* path = operation_data->delayed_arg; 204 }
238
239 Eio_File *handle = operation_data->direct_func(path,
240 _file_direct_ls_filter_cb,
241 _file_direct_ls_main_cb,
242 _file_done_cb,
243 _file_error_cb,
244 operation_data);
245 operation_data->file = handle;
246}
247 205
248static void 206 efl_promise_progress_set(p, existing);
249_free_notify_start_data(void *data) 207 efl_key_data_set(p, "_eio.stored", NULL);
250{ 208 _cleanup_string_progress(existing);
251 Job_Closure *operation_data = (Job_Closure*)data;
252 if (!operation_data->delayed_arg)
253 return;
254 free(operation_data->delayed_arg);
255 operation_data->delayed_arg = NULL;
256} 209}
257 210
211/* Direct listing callbacks */
258static void 212static void
259_ls_notify_start(void *data, Eina_Promise_Owner* promise EINA_UNUSED) 213_file_info_cb(void *data, Eio_File *handler, Eina_Array *gather)
260{ 214{
261 Job_Closure *operation_data = (Job_Closure*)data; 215 Efl_Promise *p = data;
262 char* path = operation_data->delayed_arg; 216 Eina_Array *existing = efl_key_data_get(p, "_eio.stored");
263 217 void **tmp;
264 Eio_File *handle = eio_file_ls(path,
265 _file_ls_filter_named_cb,
266 _file_ls_main_cb,
267 _file_done_cb,
268 _file_error_cb,
269 operation_data);
270 operation_data->file = handle;
271}
272 218
273static void 219 // If a future is set, but without progress, we should assume
274_xattr_notify_start(void *data, Eina_Promise_Owner *promise EINA_UNUSED) 220 // that we should discard all future progress. [[FIXME]]
275{ 221 if (existing)
276 Job_Closure *operation_data = (Job_Closure*)data; 222 {
277 char* path = operation_data->delayed_arg; 223 tmp = realloc(existing->data, sizeof (void*) * (existing->count + gather->count));
278 224 if (!tmp)
279 Eio_File *handle = eio_file_xattr(path, 225 {
280 _file_ls_filter_xattr_cb, 226 eina_array_free(gather);
281 _file_ls_main_cb, 227 eina_array_free(existing);
282 _file_done_cb, 228 efl_key_data_set(p, "_eio.stored", NULL);
283 _file_error_cb, 229 handler->error = ENOMEM;
284 operation_data); 230 eio_file_cancel(handler);
285 operation_data->file = handle; 231 return ;
232 }
233 existing->data = tmp;
234 memcpy(existing->data + existing->count, gather->data, gather->count * sizeof (void*));
235 existing->count += gather->count;
236 existing->total = existing->count;
237 eina_array_free(gather);
238 }
239 else
240 {
241 existing = gather;
242 }
243 if (!efl_key_data_get(p, "_eio.progress"))
244 {
245 efl_key_data_set(p, "_eio.stored", existing);
246 return ;
247 }
248 efl_promise_progress_set(p, existing);
249 efl_key_data_set(p, "_eio.stored", NULL);
250 _cleanup_info_progress(existing);
286} 251}
287 252
288static void 253/* Method implementations */
289_job_direct_ls_helper(Efl_Io_Manager_Direct_Ls_Func ls_func, 254static Efl_Future *
290 Eo* obj, 255_efl_io_manager_direct_ls(Eo *obj,
291 Efl_Io_Manager_Data *pd, 256 Efl_Io_Manager_Data *pd EINA_UNUSED,
292 const char *path, 257 const char *path,
293 Eina_Promise_Owner *promise) 258 Eina_Bool recursive)
294{ 259{
295 Job_Closure *operation_data = _job_closure_create(obj, pd, promise); 260 Efl_Promise *p;
261 Eio_File *h;
296 262
297 if (!operation_data) 263 p = efl_add(EFL_PROMISE_CLASS, obj);
264 if (!p) return NULL;
265
266 if (!recursive)
298 { 267 {
299 EINA_LOG_CRIT("Failed to create eio job operation data."); 268 h = _eio_file_direct_ls(path,
300 eina_promise_owner_error_set(promise, eina_error_get()); 269 _file_info_cb,
301 eina_error_set(0); 270 _file_done_cb,
302 return; 271 _file_error_cb,
272 p);
273 }
274 else
275 {
276 h = _eio_dir_direct_ls(path,
277 _file_info_cb,
278 _file_done_cb,
279 _file_error_cb,
280 p);
303 } 281 }
304 282
305 operation_data->delayed_arg = (char*)calloc(sizeof(char), strlen(path) + 1); 283 if (!h) goto end;
306 strcpy(operation_data->delayed_arg, path);
307 284
308 operation_data->direct_func = ls_func; 285 efl_event_callback_array_add(p, promise_progress_handling(), h);
286 return efl_promise_future_get(p);
309 287
310 eina_promise_owner_progress_notify(promise, 288 end:
311 _ls_direct_notify_start, 289 efl_del(p);
312 operation_data, 290 return NULL;
313 _free_notify_start_data);
314} 291}
315 292
316/* Method implementations */ 293static Efl_Future *
317 294_efl_io_manager_stat_ls(Eo *obj,
318static Eina_Promise* 295 Efl_Io_Manager_Data *pd EINA_UNUSED,
319_efl_io_manager_file_direct_ls(Eo *obj, 296 const char *path,
320 Efl_Io_Manager_Data *pd, 297 Eina_Bool recursive)
321 const char *path)
322{ 298{
323 Eina_Promise_Owner* promise = eina_promise_add(); 299 Efl_Promise *p;
324 _job_direct_ls_helper(&eio_file_direct_ls, obj, pd, path, promise); 300 Eio_File *h;
325 return eina_promise_owner_promise_get(promise);
326}
327 301
328static Eina_Promise* 302 p = efl_add(EFL_PROMISE_CLASS, obj);
329_efl_io_manager_file_stat_ls(Eo *obj, 303 if (!p) return NULL;
330 Efl_Io_Manager_Data *pd,
331 const char *path)
332{
333 Eina_Promise_Owner* promise = eina_promise_add();
334 _job_direct_ls_helper(&eio_file_stat_ls, obj, pd, path, promise);
335 return eina_promise_owner_promise_get(promise);
336}
337 304
338static Eina_Promise* 305 if (!recursive)
339_efl_io_manager_dir_stat_ls(Eo *obj, 306 {
340 Efl_Io_Manager_Data *pd, 307 h = _eio_file_stat_ls(path,
341 const char *path) 308 _file_info_cb,
342{ 309 _file_done_cb,
343 Eina_Promise_Owner* promise = eina_promise_add(); 310 _file_error_cb,
344 _job_direct_ls_helper(&eio_dir_stat_ls, obj, pd, path, promise); 311 p);
345 return eina_promise_owner_promise_get(promise); 312 }
346} 313 else
314 {
315 h = _eio_dir_stat_ls(path,
316 _file_info_cb,
317 _file_done_cb,
318 _file_error_cb,
319 p);
320 }
347 321
348static Eina_Promise* 322 if (!h) goto end;
349_efl_io_manager_dir_direct_ls(Eo *obj, 323
350 Efl_Io_Manager_Data *pd, 324 efl_event_callback_array_add(p, promise_progress_handling(), h);
351 const char *path) 325 return efl_promise_future_get(p);
352{ 326
353 Eina_Promise_Owner* promise = eina_promise_add(); 327 end:
354 // Had to add the cast as dir_direct differs in the filter callback constness of one of 328 efl_del(p);
355 // its arguments. 329 return NULL;
356 _job_direct_ls_helper((Efl_Io_Manager_Direct_Ls_Func)&eio_dir_direct_ls, obj, pd, path, promise);
357 return eina_promise_owner_promise_get(promise);
358} 330}
359 331
360static Eina_Promise* 332static Efl_Future *
361_efl_io_manager_file_ls(Eo *obj, 333_efl_io_manager_ls(Eo *obj,
362 Efl_Io_Manager_Data *pd, 334 Efl_Io_Manager_Data *pd EINA_UNUSED,
363 const char *path) 335 const char *path)
364{ 336{
365 Eina_Promise_Owner* promise = eina_promise_add(); 337 Efl_Promise *p;
366 Job_Closure *operation_data = _job_closure_create(obj, pd, promise); 338 Eio_File *h;
367 339
368 Eina_Promise* p = eina_promise_owner_promise_get(promise); 340 p = efl_add(EFL_PROMISE_CLASS, obj);
369 if (!operation_data) 341 if (!p) return NULL;
370 {
371 EINA_LOG_CRIT("Failed to create eio job operation data.");
372 eina_promise_owner_error_set(promise, eina_error_get());
373 eina_error_set(0);
374 return p;
375 }
376 342
377 operation_data->delayed_arg = (char*)calloc(sizeof(char), strlen(path) + 1); 343 h = _eio_file_ls(path,
378 strcpy(operation_data->delayed_arg, path); 344 _file_string_cb,
345 _file_done_cb,
346 _file_error_cb,
347 p);
348 if (!h) goto end;
379 349
380 eina_promise_owner_progress_notify(promise, 350 efl_event_callback_array_add(p, promise_progress_handling(), h);
381 _ls_notify_start, 351 return efl_promise_future_get(p);
382 operation_data, 352
383 _free_notify_start_data); 353 end:
384 return p; 354 efl_del(p);
355 return NULL;
385} 356}
386 357
387/* Stat function */ 358/* Stat function */
388
389static void 359static void
390_file_stat_done_cb(void *data, Eio_File *handle EINA_UNUSED, const Eina_Stat *stat) 360_file_stat_done_cb(void *data, Eio_File *handle EINA_UNUSED, const Eina_Stat *stat)
391{ 361{
392 Job_Closure *operation = data; 362 Efl_Promise *p = data;
363 Eina_Stat *c;
393 364
394 EINA_SAFETY_ON_NULL_RETURN(operation); 365 c = calloc(1, sizeof (Eina_Stat));
395 EINA_SAFETY_ON_NULL_RETURN(operation->promise); 366 if (!c)
396 Eina_Stat *my_stat = calloc(sizeof(Eina_Stat), 1); 367 {
368 efl_promise_failed(p, ENOMEM);
369 goto end;
370 }
397 371
398 *my_stat = *stat; 372 memcpy(c, stat, sizeof (Eina_Stat));
399 eina_promise_owner_value_set(operation->promise, my_stat, free); 373 efl_promise_value_set(p, c, free);
400 374
401 _job_closure_del(operation); 375 end:
376 efl_del(p);
402} 377}
403 378
404static Eina_Promise* 379static Efl_Future *
405_efl_io_manager_file_direct_stat(Eo *obj, 380_efl_io_manager_stat(Eo *obj,
406 Efl_Io_Manager_Data *pd, 381 Efl_Io_Manager_Data *pd EINA_UNUSED,
407 const char *path) 382 const char *path)
408{ 383{
409 Eina_Promise_Owner* promise = eina_promise_add(); 384 Efl_Promise *p;
410 Job_Closure *operation_data = _job_closure_create(obj, pd, promise); 385 Eio_File *h;
411 386
412 Eina_Promise* p = eina_promise_owner_promise_get(promise); 387 p = efl_add(EFL_PROMISE_CLASS, obj);
413 if (!operation_data) 388 if (!p) return NULL;
414 {
415 EINA_LOG_CRIT("Failed to create eio job operation data.");
416 eina_promise_owner_error_set(promise, eina_error_get());
417 eina_error_set(0);
418 return p;
419 }
420 389
421 Eio_File *handle = eio_file_direct_stat(path, 390 h = eio_file_direct_stat(path,
422 _file_stat_done_cb, 391 _file_stat_done_cb,
423 _file_error_cb, 392 _file_error_cb,
424 operation_data); 393 p);
425 operation_data->file = handle; 394 if (!h) goto end;
426 return p; 395
396 efl_event_callback_array_add(p, promise_handling(), h);
397 return efl_promise_future_get(p);
398
399 end:
400 efl_del(p);
401 return NULL;
427} 402}
428 403
429/* eXtended attribute manipulation */ 404/* eXtended attribute manipulation */
430 405
431static Eina_Promise* 406static Efl_Future *
432_efl_io_manager_file_xattr_list_get(Eo *obj, 407_efl_io_manager_xattr_ls(Eo *obj,
433 Efl_Io_Manager_Data *pd, 408 Efl_Io_Manager_Data *pd,
434 const char *path) 409 const char *path)
435{ 410{
411 // FIXME
412#if 0
436 Eina_Promise_Owner *promise = eina_promise_add(); 413 Eina_Promise_Owner *promise = eina_promise_add();
437 Job_Closure *operation_data = _job_closure_create(obj, pd, promise); 414 Job_Closure *operation_data = _job_closure_create(obj, pd, promise);
438 415
@@ -453,149 +430,128 @@ _efl_io_manager_file_xattr_list_get(Eo *obj,
453 operation_data, 430 operation_data,
454 _free_notify_start_data); 431 _free_notify_start_data);
455 return p; 432 return p;
433#endif
456} 434}
457 435
458static Eina_Promise* 436static Efl_Future *
459_efl_io_manager_file_xattr_set(Eo *obj, 437_efl_io_manager_xattr_set(Eo *obj,
460 Efl_Io_Manager_Data *pd, 438 Efl_Io_Manager_Data *pd EINA_UNUSED,
461 const char *path, 439 const char *path,
462 const char *attribute, 440 const char *attribute,
463 const char *xattr_data, 441 Eina_Binbuf *data,
464 unsigned int xattr_size, 442 Eina_Xattr_Flags flags)
465 Eina_Xattr_Flags flags)
466{ 443{
467 Eina_Promise_Owner* promise = eina_promise_add(); 444 Efl_Promise *p;
468 Job_Closure *operation_data = _job_closure_create(obj, pd, promise); 445 Eio_File *h;
469 446
470 Eina_Promise* p = eina_promise_owner_promise_get(promise); 447 p = efl_add(EFL_PROMISE_CLASS, obj);
448 if (!p) return NULL;
471 449
472 if (!operation_data) 450 h = eio_file_xattr_set(path, attribute,
473 { 451 (const char *) eina_binbuf_string_get(data),
474 EINA_LOG_CRIT("Failed to create eio job operation data."); 452 eina_binbuf_length_get(data),
475 eina_promise_owner_error_set(promise, eina_error_get()); 453 flags,
476 eina_error_set(0); 454 _file_done_cb,
477 return p; 455 _file_error_cb,
478 } 456 p);
457 if (!h) goto end;
479 458
480 Eio_File *handle = eio_file_xattr_set(path, 459 efl_event_callback_array_add(p, promise_handling(), h);
481 attribute, 460 return efl_promise_future_get(p);
482 xattr_data, 461
483 xattr_size, 462 end:
484 flags, 463 efl_del(p);
485 _file_done_cb, 464 return NULL;
486 _file_error_cb,
487 operation_data);
488 operation_data->file = handle;
489 return p;
490} 465}
491 466
492static Eina_Promise* 467static Efl_Future *
493_efl_io_manager_file_xattr_get(Eo *obj, 468_efl_io_manager_xattr_get(Eo *obj,
494 Efl_Io_Manager_Data *pd, 469 Efl_Io_Manager_Data *pd EINA_UNUSED,
495 const char *path, 470 const char *path,
496 const char *attribute) 471 const char *attribute)
497{ 472{
498 Eina_Promise_Owner* promise = eina_promise_add(); 473 Efl_Promise *p;
499 Job_Closure *operation_data = _job_closure_create(obj, pd, promise); 474 Eio_File *h;
500 475
501 Eina_Promise* p = eina_promise_owner_promise_get(promise); 476 p = efl_add(EFL_PROMISE_CLASS, obj);
502 if (!operation_data) 477 if (!p) return NULL;
503 {
504 EINA_LOG_CRIT("Failed to create eio job operation data.");
505 eina_promise_owner_error_set(promise, eina_error_get());
506 eina_error_set(0);
507 return p;
508 }
509 478
510 Eio_File *handle = eio_file_xattr_get(path, 479 h = eio_file_xattr_get(path, attribute,
511 attribute, 480 _file_done_data_cb,
512 _file_done_data_cb, 481 _file_error_cb,
513 _file_error_cb, 482 p);
514 operation_data); 483 if (!h) goto end;
515 operation_data->file = handle;
516 return p;
517}
518 484
519static void 485 efl_event_callback_array_add(p, promise_handling(), h);
520_file_open_open_cb(void *data, Eio_File *handler EINA_UNUSED, Eina_File *file) 486 return efl_promise_future_get(p);
521{
522 Job_Closure *operation = data;
523 EINA_SAFETY_ON_NULL_RETURN(operation);
524 EINA_SAFETY_ON_NULL_RETURN(operation->promise);
525 eina_promise_owner_value_set(operation->promise, file, (Eina_Promise_Free_Cb)&eina_file_close);
526 487
527 _job_closure_del(operation); 488 end:
489 efl_del(p);
490 return NULL;
528} 491}
529 492
530static Eina_Promise* 493static void
531_efl_io_manager_file_open(Eo *obj, 494_file_open_cb(void *data, Eio_File *handler, Eina_File *file)
532 Efl_Io_Manager_Data *pd,
533 const char *path,
534 Eina_Bool shared)
535{ 495{
536 Eina_Promise_Owner* promise = eina_promise_add(); 496 Efl_Promise *p = data;
537 Job_Closure *operation_data = _job_closure_create(obj, pd, promise);
538 497
539 Eina_Promise* p = eina_promise_owner_promise_get(promise); 498 efl_event_callback_array_del(p, promise_handling(), handler);
540 if (!operation_data)
541 {
542 EINA_LOG_CRIT("Failed to create eio job operation data.");
543 eina_promise_owner_error_set(promise, eina_error_get());
544 eina_error_set(0);
545 return p;
546 }
547 499
548 Eio_File *handle = eio_file_open(path, shared, _file_open_open_cb, _file_error_cb, operation_data); 500 efl_promise_value_set(p, eina_file_dup(file), EINA_FREE_CB(eina_file_close));
549 operation_data->file = handle;
550 return p;
551}
552 501
502 efl_del(p);
503}
553 504
554static void 505static Efl_Future *
555_file_close_done_cb(void *data, Eio_File *handler EINA_UNUSED) 506_efl_io_manager_open(Eo *obj,
507 Efl_Io_Manager_Data *pd EINA_UNUSED,
508 const char *path,
509 Eina_Bool shared)
556{ 510{
557 EINA_SAFETY_ON_NULL_RETURN(data); 511 Efl_Promise *p;
558 Job_Closure *operation = data; 512 Eio_File *h;
559 eina_promise_owner_value_set(operation->promise, NULL, NULL);
560 513
561 _job_closure_del(operation); 514 p = efl_add(EFL_PROMISE_CLASS, obj);
562} 515 if (!p) return NULL;
563 516
564static void 517 h = eio_file_open(path, shared,
565_efl_io_manager_file_close(Eo *obj, 518 _file_open_cb,
566 Efl_Io_Manager_Data *pd, 519 _file_error_cb,
567 Eina_File *file, 520 p);
568 Eina_Promise_Owner *promise)
569{
570 Job_Closure *operation_data = _job_closure_create(obj, pd, promise);
571 521
572 if (!operation_data) 522 if (!h) goto end;
573 { 523
574 EINA_LOG_CRIT("Failed to create eio job operation data."); 524 efl_event_callback_array_add(p, promise_handling(), h);
575 return; 525 return efl_promise_future_get(p);
576 }
577 526
578 Eio_File *handle = eio_file_close(file, _file_close_done_cb, _file_error_cb, operation_data); 527 end:
579 operation_data->file = handle; 528 efl_del(p);
529 return NULL;
580} 530}
581 531
582static Efl_Object* 532static Efl_Future *
583_efl_io_manager_efl_object_constructor(Eo *obj, Efl_Io_Manager_Data *pd EINA_UNUSED) 533_efl_io_manager_close(Eo *obj,
534 Efl_Io_Manager_Data *pd EINA_UNUSED,
535 Eina_File *file)
584{ 536{
585 obj = efl_constructor(efl_super(obj, EFL_IO_MANAGER_CLASS)); 537 Efl_Promise *p;
538 Eio_File *h;
586 539
587 pd->object = obj; 540 p = efl_add(EFL_PROMISE_CLASS, obj);
588 pd->operations = NULL; 541 if (!p) return NULL;
589 542
590 return obj; 543 h = eio_file_close(file,
591} 544 _file_done_cb,
545 _file_error_cb,
546 p);
547 if (!h) goto end;
592 548
593static void 549 efl_event_callback_array_add(p, promise_handling(), h);
594_efl_io_manager_efl_object_destructor(Eo *obj, Efl_Io_Manager_Data *pd EINA_UNUSED) 550 return efl_promise_future_get(p);
595{
596 efl_destructor(efl_super(obj, EFL_IO_MANAGER_CLASS));
597 551
598 // FIXME: cancel all pending promise 552 end:
553 efl_del(p);
554 return NULL;
599} 555}
600 556
601#include "efl_io_manager.eo.c" 557#include "efl_io_manager.eo.c"
diff --git a/src/lib/eio/efl_io_manager.eo b/src/lib/eio/efl_io_manager.eo
index f41a176757..05304c27bc 100644
--- a/src/lib/eio/efl_io_manager.eo
+++ b/src/lib/eio/efl_io_manager.eo
@@ -7,118 +7,75 @@ struct Eio.Data
7 size: uint; 7 size: uint;
8} 8}
9 9
10// FIXME: all events should be Eo objects not data if we want to modify them 10class Efl.Io.Manager (Efl.Loop_User)
11
12struct Eio.Filter.Direct.Data
13{
14 info: const(Eina.File.Direct.Info)*;
15 filter: bool;
16}
17
18struct Eio.Filter.Name.Data
19{
20 file: string;
21 filter: bool;
22}
23
24struct Eio.Xattr.Data
25{
26 data: string;
27 size: uint;
28}
29
30// FIXME: We should send list of stuff in progress not single item, callback cost is to high
31
32class Efl.Io.Manager (Efl.Object)
33{ 11{
34 [[Class representing an asynchronous file operation.]] 12 [[Class representing an asynchronous file operation.]]
35 13
36 methods { 14 methods {
37 15 ls {
38 file_ls {
39 [[Lists entries in a given path.]] 16 [[Lists entries in a given path.]]
40 params { 17 params {
41 @in path: string; 18 @in path: string;
42 } 19 }
43 return: promise<int, string>; 20 return: future<uint64, const(array<string>)>;
44 } 21 }
45 22
46 file_direct_ls { 23 direct_ls {
47 [[Lists entries in a given path with more information.]] 24 [[Lists entries in a given path with more information.]]
48 params { 25 params {
49 @in path: string; 26 @in path: string;
27 @in recursive: bool;
50 } 28 }
51 return: promise<int, const(Eina_File_Direct_Info)*>; 29 return: future<uint64, const(array<Eina_File_Direct_Info>)>;
52 } 30 }
53 31
54 file_stat_ls { 32 stat_ls {
55 [[Lists entries in a given path with stat information.]] 33 [[Lists entries in a given path with stat information.]]
56 params { 34 params {
57 @in path: string; 35 @in path: string;
36 @in recursive: bool;
58 } 37 }
59 return: promise<int, const(Eina_File_Direct_Info)*>; 38 return: future<uint64, const(array<Eina_File_Direct_Info>)>;
60 } 39 }
61 40
62 dir_stat_ls { 41 // Extended attributes
63 [[Recursively list the directory content and its sub content.]] 42 xattr_ls {
64 params { 43 [[Lists all extended attributes asynchronously.]]
65 @in path: string;
66 }
67 return: promise<int, const(Eina_File_Direct_Info)*>;
68 }
69
70 dir_direct_ls {
71 [[Recursively list the directory content and its sub content.]]
72 params { 44 params {
73 @in path: string; 45 @in path: string;
74 } 46 }
75 return: promise<int, const(Eina_File_Direct_Info)*>; 47 return: future<uint64, const(array<string>)>;
76 } 48 }
77 49
78 file_direct_stat { 50 stat {
79 [[Get stat info on a given file/directory.]] 51 [[Get stat info on a given file/directory.]]
80 params { 52 params {
81 @in path: string; 53 @in path: string;
82 } 54 }
83 return: promise<Eina_Stat>; 55 return: future<Eina_Stat>;
84 }
85
86 // Extended attributes
87 @property file_xattr_list {
88 [[Lists all extended attributes asynchronously.]]
89 keys {
90 path: string;
91 }
92 get {
93 return: promise<int, string>;
94 }
95 } 56 }
96 57
97 @property file_xattr { 58 // FIXME: Add helper for Eina.Value to Xattr
59 @property xattr {
98 [[Retrieves or sets information of a given extended attribute.]] 60 [[Retrieves or sets information of a given extended attribute.]]
99 set { 61 set {
100 values { 62 values {
101 attribute: string; 63 data: Eina.Binbuf *;
102 xattr_data: string;
103 xattr_size: uint;
104 flags: Eina.Xattr.Flags; 64 flags: Eina.Xattr.Flags;
105 } 65 }
106 return: promise<int>; 66 return: future<uint64>;
107 } 67 }
108 get { 68 get {
109 keys { 69 return: future<Eina.Binbuf>;
110 path: string;
111 attribute: string;
112 }
113 return: promise<Eio.Xattr.Data>;
114 } 70 }
115 keys { 71 keys {
116 path: string; 72 path: string;
73 attribute: string;
117 } 74 }
118 } 75 }
119 76
120 // helper api 77 // helper api
121 file_open { 78 open {
122 [[Opens a file. 79 [[Opens a file.
123 80
124 The fulfilled value in the promise will be the Eina.File*.]] 81 The fulfilled value in the promise will be the Eina.File*.]]
@@ -126,25 +83,15 @@ class Efl.Io.Manager (Efl.Object)
126 @in path: string; 83 @in path: string;
127 @in shared: bool; 84 @in shared: bool;
128 } 85 }
129 return: promise<Eina.File*>; 86 return: future<Eina.File>;
130 } 87 }
131 file_close { 88 close {
132 [[Closes an open Eina.File.]] 89 [[Closes an open Eina.File.]]
133 params { 90 params {
134 @in file: Eina.File*; 91 @in file: Eina.File*;
135 // Here we're just interested whether the promise was fullfilled or not. No value needed. 92 // Here we're just interested whether the promise was fullfilled or not. No value needed.
136 @inout promise: promise<int>;
137 } 93 }
94 return: future<int>;
138 } 95 }
139 } 96 }
140 events {
141 filter,name: Eio.Filter.Name.Data;
142 filter,direct: Eio.Filter.Direct.Data;
143 xattr: Eio.Filter.Name.Data;
144 }
145
146 implements {
147 Efl.Object.constructor;
148 Efl.Object.destructor;
149 }
150} 97}