00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdlib.h>
00026 #include <errno.h>
00027
00028 #include "buffer.h"
00029 #include "buffer_internal.h"
00030 #include "buffer_source.h"
00031 #include "buffer_action.h"
00032 #include "buffer_action_internal.h"
00033 #include "buffer_action_edit.h"
00034 #include "buffer_util.h"
00035 #include "segcol.h"
00036 #include "data_object.h"
00037 #include "data_object_memory.h"
00038 #include "debug.h"
00039
00040
00041
00042
00043
00044 static int create_segment_from_source(segment_t **seg,
00045 bless_buffer_source_t *src, off_t src_offset, off_t length);
00046 static int segment_inplace_private_copy(segment_t *seg, data_object_t *cmp_dobj);
00047 static int segcol_inplace_private_copy(segcol_t *segcol, data_object_t *cmp_dobj);
00048
00049
00050 static int buffer_action_append_do(buffer_action_t *action);
00051 static int buffer_action_append_undo(buffer_action_t *action);
00052 static int buffer_action_append_private_copy(buffer_action_t *action,
00053 data_object_t *dobj);
00054 static int buffer_action_append_to_event(buffer_action_t *action,
00055 struct bless_buffer_event_info *event_info);
00056 static int buffer_action_append_free(buffer_action_t *action);
00057
00058
00059 static int buffer_action_insert_do(buffer_action_t *action);
00060 static int buffer_action_insert_undo(buffer_action_t *action);
00061 static int buffer_action_insert_private_copy(buffer_action_t *action,
00062 data_object_t *dobj);
00063 static int buffer_action_insert_to_event(buffer_action_t *action,
00064 struct bless_buffer_event_info *event_info);
00065 static int buffer_action_insert_free(buffer_action_t *action);
00066
00067 static int buffer_action_delete_do(buffer_action_t *action);
00068 static int buffer_action_delete_undo(buffer_action_t *action);
00069 static int buffer_action_delete_private_copy(buffer_action_t *action,
00070 data_object_t *dobj);
00071 static int buffer_action_delete_to_event(buffer_action_t *action,
00072 struct bless_buffer_event_info *event_info);
00073 static int buffer_action_delete_free(buffer_action_t *action);
00074
00075 static int buffer_action_multi_do(buffer_action_t *action);
00076 static int buffer_action_multi_undo(buffer_action_t *action);
00077 static int buffer_action_multi_private_copy(buffer_action_t *action,
00078 data_object_t *dobj);
00079 static int buffer_action_multi_to_event(buffer_action_t *action,
00080 struct bless_buffer_event_info *event_info);
00081 static int buffer_action_multi_free(buffer_action_t *action);
00082
00083
00084 static struct buffer_action_funcs buffer_action_append_funcs = {
00085 .do_func = buffer_action_append_do,
00086 .undo_func = buffer_action_append_undo,
00087 .private_copy_func = buffer_action_append_private_copy,
00088 .to_event_func = buffer_action_append_to_event,
00089 .free_func = buffer_action_append_free
00090 };
00091
00092 static struct buffer_action_funcs buffer_action_insert_funcs = {
00093 .do_func = buffer_action_insert_do,
00094 .undo_func = buffer_action_insert_undo,
00095 .private_copy_func = buffer_action_insert_private_copy,
00096 .to_event_func = buffer_action_insert_to_event,
00097 .free_func = buffer_action_insert_free
00098 };
00099
00100 static struct buffer_action_funcs buffer_action_delete_funcs = {
00101 .do_func = buffer_action_delete_do,
00102 .undo_func = buffer_action_delete_undo,
00103 .private_copy_func = buffer_action_delete_private_copy,
00104 .to_event_func = buffer_action_delete_to_event,
00105 .free_func = buffer_action_delete_free
00106 };
00107
00108 static struct buffer_action_funcs buffer_action_multi_funcs = {
00109 .do_func = buffer_action_multi_do,
00110 .undo_func = buffer_action_multi_undo,
00111 .private_copy_func = buffer_action_multi_private_copy,
00112 .to_event_func = buffer_action_multi_to_event,
00113 .free_func = buffer_action_multi_free
00114 };
00115
00116
00117 struct buffer_action_append_impl {
00118 bless_buffer_t *buf;
00119 segment_t *seg;
00120 };
00121
00122 struct buffer_action_insert_impl {
00123 bless_buffer_t *buf;
00124 off_t offset;
00125 segment_t *seg;
00126 };
00127
00128 struct buffer_action_delete_impl {
00129 bless_buffer_t *buf;
00130 off_t offset;
00131 off_t length;
00132 segcol_t *deleted;
00133 };
00134
00135 struct buffer_action_multi_impl {
00136 bless_buffer_t *buf;
00137 list_t *action_list;
00138 };
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static int create_segment_from_source(segment_t **seg,
00155 bless_buffer_source_t *src, off_t src_offset, off_t length)
00156 {
00157 data_object_t *dobj = (data_object_t *) src;
00158
00159 int err = segment_new(seg, dobj, src_offset, length,
00160 data_object_update_usage);
00161 if (err)
00162 return_error(err);
00163
00164
00165
00166
00167
00168 off_t dobj_size;
00169 err = data_object_get_size(dobj, &dobj_size);
00170 if (err)
00171 goto fail;
00172
00173 if (src_offset + length - 1 * (length != 0) >= dobj_size) {
00174 err = EINVAL;
00175 goto fail;
00176 }
00177
00178 return 0;
00179
00180 fail:
00181
00182 segment_free(*seg);
00183 return_error(err);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 static int segment_inplace_private_copy(segment_t *seg, data_object_t *cmp_dobj)
00199 {
00200 data_object_t *seg_dobj;
00201 off_t seg_start;
00202 off_t seg_size;
00203
00204
00205 int err = segment_get_data(seg, (void **)&seg_dobj);
00206 if (err)
00207 return_error(err);
00208
00209
00210 int result;
00211 err = data_object_compare(&result, seg_dobj, cmp_dobj);
00212 if (err)
00213 return_error(err);
00214 if (result != 0)
00215 return 0;
00216
00217 err = segment_get_start(seg, &seg_start);
00218 if (err)
00219 return_error(err);
00220 err = segment_get_size(seg, &seg_size);
00221 if (err)
00222 return_error(err);
00223
00224
00225 void *new_data = malloc(seg_size);
00226 if (new_data == NULL)
00227 return_error(ENOMEM);
00228
00229 data_object_t *new_dobj;
00230 err = data_object_memory_new(&new_dobj, new_data, seg_size);
00231 if (err) {
00232 free(new_data);
00233 return_error(err);
00234 }
00235
00236
00237 err = data_object_memory_set_free_func(new_dobj, free);
00238 if (err) {
00239 free(new_data);
00240 data_object_free(new_dobj);
00241 return_error(err);
00242 }
00243
00244
00245 err = read_data_object(seg_dobj, seg_start, new_data, seg_size);
00246 if (err) {
00247 data_object_free(new_dobj);
00248 return_error(err);
00249 }
00250
00251 err = segment_set_range(seg, 0, seg_size);
00252 if (err) {
00253 data_object_free(new_dobj);
00254 return_error(err);
00255 }
00256
00257 err = segment_set_data(seg, new_dobj, data_object_update_usage);
00258 if (err) {
00259 segment_set_range(seg, seg_start, seg_size);
00260 data_object_free(new_dobj);
00261 return_error(err);
00262 }
00263
00264
00265 return 0;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 static int segcol_inplace_private_copy(segcol_t *segcol, data_object_t *cmp_dobj)
00282 {
00283 segcol_iter_t *iter;
00284 int err = segcol_iter_new(segcol, &iter);
00285 if (err)
00286 return_error(err);
00287
00288 int iter_valid;
00289
00290
00291
00292
00293 while (!(err = segcol_iter_is_valid(iter, &iter_valid)) && iter_valid) {
00294 segment_t *seg;
00295
00296 err = segcol_iter_get_segment(iter, &seg);
00297 if (err)
00298 goto fail;
00299
00300
00301 err = segment_inplace_private_copy(seg, cmp_dobj);
00302 if (err)
00303 goto fail;
00304
00305 err = segcol_iter_next(iter);
00306 if (err)
00307 goto fail;
00308
00309 }
00310
00311 segcol_iter_free(iter);
00312
00313 return 0;
00314
00315 fail:
00316 segcol_iter_free(iter);
00317 return_error(err);
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 int buffer_action_append_new(buffer_action_t **action, bless_buffer_t *buf,
00336 bless_buffer_source_t *src, off_t src_offset, off_t length)
00337 {
00338 if (action == NULL || buf == NULL || src == NULL)
00339 return_error(EINVAL);
00340
00341
00342 struct buffer_action_append_impl *impl =
00343 malloc(sizeof(struct buffer_action_append_impl));
00344
00345 if (impl == NULL)
00346 return_error(EINVAL);
00347
00348
00349 int err = buffer_action_create_impl(action, impl,
00350 &buffer_action_append_funcs);
00351
00352 if (err)
00353 goto fail;
00354
00355
00356 err = create_segment_from_source(&impl->seg, src, src_offset, length);
00357 if (err)
00358 goto fail_segment;
00359
00360 impl->buf = buf;
00361
00362 return 0;
00363
00364 fail_segment:
00365 free(*action);
00366 fail:
00367 free(impl);
00368 return_error(err);
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 int buffer_action_insert_new(buffer_action_t **action, bless_buffer_t *buf,
00384 off_t offset, bless_buffer_source_t *src, off_t src_offset, off_t length)
00385 {
00386 if (action == NULL || buf == NULL || src == NULL)
00387 return_error(EINVAL);
00388
00389
00390 struct buffer_action_insert_impl *impl =
00391 malloc(sizeof(struct buffer_action_insert_impl));
00392
00393 if (impl == NULL)
00394 return_error(EINVAL);
00395
00396
00397 int err = buffer_action_create_impl(action, impl,
00398 &buffer_action_insert_funcs);
00399
00400 if (err)
00401 goto fail;
00402
00403
00404 err = create_segment_from_source(&impl->seg, src, src_offset, length);
00405 if (err)
00406 goto fail_segment;
00407
00408 impl->buf = buf;
00409 impl->offset = offset;
00410
00411 return 0;
00412
00413 fail_segment:
00414 free(*action);
00415 fail:
00416 free(impl);
00417 return_error(err);
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 int buffer_action_delete_new(buffer_action_t **action, bless_buffer_t *buf,
00431 off_t offset, off_t length)
00432 {
00433 if (action == NULL || buf == NULL)
00434 return_error(EINVAL);
00435
00436
00437 struct buffer_action_delete_impl *impl =
00438 malloc(sizeof(struct buffer_action_delete_impl));
00439
00440 if (impl == NULL)
00441 return_error(EINVAL);
00442
00443
00444 int err = buffer_action_create_impl(action, impl,
00445 &buffer_action_delete_funcs);
00446
00447 if (err)
00448 goto fail;
00449
00450
00451 impl->buf = buf;
00452 impl->offset = offset;
00453 impl->length = length;
00454 impl->deleted = NULL;
00455
00456 return 0;
00457
00458 fail:
00459 free(impl);
00460 return_error(err);
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470 int buffer_action_multi_new(buffer_action_t **action)
00471 {
00472 if (action == NULL)
00473 return_error(EINVAL);
00474
00475
00476 struct buffer_action_multi_impl *impl =
00477 malloc(sizeof(struct buffer_action_multi_impl));
00478
00479 if (impl == NULL)
00480 return_error(EINVAL);
00481
00482
00483 int err = buffer_action_create_impl(action, impl,
00484 &buffer_action_multi_funcs);
00485 if (err) {
00486 free(impl);
00487 return_error(err);
00488 }
00489
00490
00491 err = list_new(&impl->action_list, struct buffer_action_entry, ln);
00492 if (err) {
00493 free(impl);
00494 return_error(err);
00495 }
00496
00497 return 0;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 int buffer_action_multi_add(buffer_action_t *multi_action, buffer_action_t *new_action)
00509 {
00510 if (multi_action == NULL || new_action == NULL)
00511 return_error(EINVAL);
00512
00513 struct buffer_action_multi_impl *impl =
00514 (struct buffer_action_multi_impl *) buffer_action_get_impl(multi_action);
00515
00516
00517 struct buffer_action_entry *entry =
00518 malloc(sizeof(struct buffer_action_entry));
00519
00520 if (entry == NULL)
00521 return_error(EINVAL);
00522
00523 entry->action = new_action;
00524
00525
00526 int err = list_insert_before(list_tail(impl->action_list), &entry->ln);
00527 if (err) {
00528 free(entry);
00529 return_error(err);
00530 }
00531
00532 return 0;
00533 }
00534
00535
00536
00537
00538
00539 static int buffer_action_append_do(buffer_action_t *action)
00540 {
00541 if (action == NULL)
00542 return_error(EINVAL);
00543
00544 struct buffer_action_append_impl *impl =
00545 (struct buffer_action_append_impl *) buffer_action_get_impl(action);
00546
00547
00548
00549
00550
00551 segment_t *seg;
00552
00553 int err = segment_copy(impl->seg, &seg);
00554 if (err)
00555 return_error(err);
00556
00557 segcol_t *sc = impl->buf->segcol;
00558
00559
00560 err = segcol_append(sc, seg);
00561 if (err)
00562 goto fail;
00563
00564 return 0;
00565
00566 fail:
00567 segment_free(seg);
00568 return_error(err);
00569 }
00570
00571 static int buffer_action_append_undo(buffer_action_t *action)
00572 {
00573 if (action == NULL)
00574 return_error(EINVAL);
00575
00576 struct buffer_action_append_impl *impl =
00577 (struct buffer_action_append_impl *) buffer_action_get_impl(action);
00578
00579
00580
00581
00582
00583 segcol_t *sc = impl->buf->segcol;
00584 off_t segcol_size;
00585 int err = segcol_get_size(sc, &segcol_size);
00586 if (err)
00587 return_error(err);
00588
00589 off_t seg_size;
00590 err = segment_get_size(impl->seg, &seg_size);
00591 if (err)
00592 return_error(err);
00593
00594
00595 err = segcol_delete(sc, NULL, segcol_size - seg_size, seg_size);
00596 if (err)
00597 return_error(err);
00598
00599 return 0;
00600 }
00601
00602 static int buffer_action_append_private_copy(buffer_action_t *action,
00603 data_object_t *cmp_dobj)
00604 {
00605 if (action == NULL || cmp_dobj == NULL)
00606 return_error(EINVAL);
00607
00608 struct buffer_action_append_impl *impl =
00609 (struct buffer_action_append_impl *) buffer_action_get_impl(action);
00610
00611 int err = segment_inplace_private_copy(impl->seg, cmp_dobj);
00612 if (err)
00613 return_error(err);
00614
00615 return 0;
00616 }
00617
00618 static int buffer_action_append_to_event(buffer_action_t *action,
00619 struct bless_buffer_event_info *event_info)
00620 {
00621 if (action == NULL || event_info == NULL)
00622 return_error(EINVAL);
00623
00624 struct buffer_action_append_impl *impl =
00625 (struct buffer_action_append_impl *) buffer_action_get_impl(action);
00626
00627 off_t buf_size;
00628 bless_buffer_get_size(impl->buf, &buf_size);
00629
00630 off_t seg_size;
00631 segment_get_size(impl->seg, &seg_size);
00632
00633 event_info->action_type = BLESS_BUFFER_ACTION_APPEND;
00634 event_info->range_start = buf_size - seg_size;
00635 event_info->range_length = seg_size;
00636 event_info->save_fd = -1;
00637
00638 return 0;
00639 }
00640
00641 static int buffer_action_append_free(buffer_action_t *action)
00642 {
00643 if (action == NULL)
00644 return_error(EINVAL);
00645
00646 struct buffer_action_append_impl *impl =
00647 (struct buffer_action_append_impl *) buffer_action_get_impl(action);
00648
00649 int err = segment_free(impl->seg);
00650 if (err)
00651 return_error(err);
00652
00653 free(impl);
00654
00655 return 0;
00656 }
00657
00658
00659
00660
00661
00662 static int buffer_action_insert_do(buffer_action_t *action)
00663 {
00664 if (action == NULL)
00665 return_error(EINVAL);
00666
00667 struct buffer_action_insert_impl *impl =
00668 (struct buffer_action_insert_impl *) buffer_action_get_impl(action);
00669
00670
00671
00672
00673
00674 segment_t *seg;
00675
00676 int err = segment_copy(impl->seg, &seg);
00677 if (err)
00678 return_error(err);
00679
00680 segcol_t *sc = impl->buf->segcol;
00681
00682
00683 err = segcol_insert(sc, impl->offset, seg);
00684 if (err)
00685 goto fail;
00686
00687 return 0;
00688 fail:
00689 segment_free(seg);
00690 return_error(err);
00691 }
00692
00693 static int buffer_action_insert_undo(buffer_action_t *action)
00694 {
00695 if (action == NULL)
00696 return_error(EINVAL);
00697
00698 struct buffer_action_insert_impl *impl =
00699 (struct buffer_action_insert_impl *) buffer_action_get_impl(action);
00700
00701
00702
00703
00704
00705 segcol_t *sc = impl->buf->segcol;
00706
00707 off_t seg_size;
00708 int err = segment_get_size(impl->seg, &seg_size);
00709 if (err)
00710 return_error(err);
00711
00712
00713 err = segcol_delete(sc, NULL, impl->offset, seg_size);
00714 if (err)
00715 return_error(err);
00716
00717 return 0;
00718 }
00719
00720 static int buffer_action_insert_private_copy(buffer_action_t *action,
00721 data_object_t *cmp_dobj)
00722 {
00723 if (action == NULL || cmp_dobj == NULL)
00724 return_error(EINVAL);
00725
00726 struct buffer_action_insert_impl *impl =
00727 (struct buffer_action_insert_impl *) buffer_action_get_impl(action);
00728
00729 int err = segment_inplace_private_copy(impl->seg, cmp_dobj);
00730 if (err)
00731 return_error(err);
00732
00733 return 0;
00734 }
00735
00736 static int buffer_action_insert_to_event(buffer_action_t *action,
00737 struct bless_buffer_event_info *event_info)
00738 {
00739 if (action == NULL || event_info == NULL)
00740 return_error(EINVAL);
00741
00742 struct buffer_action_insert_impl *impl =
00743 (struct buffer_action_insert_impl *) buffer_action_get_impl(action);
00744
00745 off_t seg_size;
00746 segment_get_size(impl->seg, &seg_size);
00747
00748 event_info->action_type = BLESS_BUFFER_ACTION_INSERT;
00749 event_info->range_start = impl->offset;
00750 event_info->range_length = seg_size;
00751 event_info->save_fd = -1;
00752
00753 return 0;
00754 }
00755
00756 static int buffer_action_insert_free(buffer_action_t *action)
00757 {
00758 if (action == NULL)
00759 return_error(EINVAL);
00760
00761 struct buffer_action_insert_impl *impl =
00762 (struct buffer_action_insert_impl *) buffer_action_get_impl(action);
00763
00764 int err = segment_free(impl->seg);
00765 if (err)
00766 return_error(err);
00767
00768 free(impl);
00769
00770 return 0;
00771 }
00772
00773
00774
00775
00776
00777 static int buffer_action_delete_do(buffer_action_t *action)
00778 {
00779 if (action == NULL)
00780 return_error(EINVAL);
00781
00782 struct buffer_action_delete_impl *impl =
00783 (struct buffer_action_delete_impl *) buffer_action_get_impl(action);
00784
00785
00786
00787
00788
00789 segcol_t *deleted;
00790 int err = segcol_delete(impl->buf->segcol, &deleted, impl->offset,
00791 impl->length);
00792
00793 if (err)
00794 return_error(err);
00795
00796
00797 if (impl->deleted != NULL) {
00798 err = segcol_free(impl->deleted);
00799 if (err) {
00800 segcol_add_copy(impl->buf->segcol, impl->offset, deleted);
00801 segcol_free(deleted);
00802 return_error(err);
00803 }
00804 }
00805
00806
00807 impl->deleted = deleted;
00808
00809 return 0;
00810 }
00811
00812 static int buffer_action_delete_undo(buffer_action_t *action)
00813 {
00814 if (action == NULL)
00815 return_error(EINVAL);
00816
00817 struct buffer_action_delete_impl *impl =
00818 (struct buffer_action_delete_impl *) buffer_action_get_impl(action);
00819
00820
00821 int err = segcol_add_copy(impl->buf->segcol, impl->offset, impl->deleted);
00822 if (err)
00823 return_error(err);
00824
00825 return 0;
00826 }
00827
00828 static int buffer_action_delete_private_copy(buffer_action_t *action,
00829 data_object_t *cmp_dobj)
00830 {
00831 if (action == NULL || cmp_dobj == NULL)
00832 return_error(EINVAL);
00833
00834 struct buffer_action_delete_impl *impl =
00835 (struct buffer_action_delete_impl *) buffer_action_get_impl(action);
00836
00837 int err = segcol_inplace_private_copy(impl->deleted, cmp_dobj);
00838 if (err)
00839 return_error(err);
00840
00841 return 0;
00842 }
00843
00844 static int buffer_action_delete_to_event(buffer_action_t *action,
00845 struct bless_buffer_event_info *event_info)
00846 {
00847 if (action == NULL || event_info == NULL)
00848 return_error(EINVAL);
00849
00850 struct buffer_action_delete_impl *impl =
00851 (struct buffer_action_delete_impl *) buffer_action_get_impl(action);
00852
00853 event_info->action_type = BLESS_BUFFER_ACTION_DELETE;
00854 event_info->range_start = impl->offset;
00855 event_info->range_length = impl->length;
00856 event_info->save_fd = -1;
00857
00858 return 0;
00859 }
00860
00861 static int buffer_action_delete_free(buffer_action_t *action)
00862 {
00863 if (action == NULL)
00864 return_error(EINVAL);
00865
00866 struct buffer_action_delete_impl *impl =
00867 (struct buffer_action_delete_impl *) buffer_action_get_impl(action);
00868
00869 if (impl->deleted != NULL) {
00870 int err = segcol_free(impl->deleted);
00871 if (err)
00872 return err;
00873 }
00874
00875 free(impl);
00876
00877 return 0;
00878 }
00879
00880
00881
00882
00883
00884 static int buffer_action_multi_do(buffer_action_t *action)
00885 {
00886 if (action == NULL)
00887 return_error(EINVAL);
00888
00889 int err = 0;
00890
00891 struct buffer_action_multi_impl *impl =
00892 (struct buffer_action_multi_impl *) buffer_action_get_impl(action);
00893
00894 struct list_node *node;
00895 list_for_each(list_head(impl->action_list)->next, node) {
00896 struct buffer_action_entry *entry =
00897 list_entry(node, struct buffer_action_entry, ln);
00898
00899 buffer_action_t *a = entry->action;
00900
00901 err = buffer_action_do(a);
00902 if (err)
00903 break;
00904 }
00905
00906 if (err) {
00907 struct list_node *start = node->prev;
00908 list_for_each_reverse(start, node) {
00909 struct buffer_action_entry *entry =
00910 list_entry(node, struct buffer_action_entry, ln);
00911
00912 buffer_action_t *a = entry->action;
00913
00914 buffer_action_undo(a);
00915 }
00916 return_error(err);
00917 }
00918
00919 return 0;
00920 }
00921
00922 static int buffer_action_multi_undo(buffer_action_t *action)
00923 {
00924 if (action == NULL)
00925 return_error(EINVAL);
00926
00927 int err = 0;
00928
00929 struct buffer_action_multi_impl *impl =
00930 (struct buffer_action_multi_impl *) buffer_action_get_impl(action);
00931
00932 struct list_node *node;
00933 list_for_each_reverse(list_tail(impl->action_list)->prev, node) {
00934 struct buffer_action_entry *entry =
00935 list_entry(node, struct buffer_action_entry, ln);
00936
00937 buffer_action_t *a = entry->action;
00938
00939 err = buffer_action_undo(a);
00940 if (err)
00941 break;
00942 }
00943
00944 if (err) {
00945 struct list_node *start = node->next;
00946 list_for_each(start, node) {
00947 struct buffer_action_entry *entry =
00948 list_entry(node, struct buffer_action_entry, ln);
00949
00950 buffer_action_t *a = entry->action;
00951
00952 buffer_action_do(a);
00953 }
00954 return_error(err);
00955 }
00956
00957 return 0;
00958 }
00959
00960 static int buffer_action_multi_private_copy(buffer_action_t *action,
00961 data_object_t *cmp_dobj)
00962 {
00963 if (action == NULL || cmp_dobj == NULL)
00964 return_error(EINVAL);
00965
00966 struct buffer_action_multi_impl *impl =
00967 (struct buffer_action_multi_impl *) buffer_action_get_impl(action);
00968
00969 struct list_node *node;
00970 list_for_each_reverse(list_tail(impl->action_list)->prev, node) {
00971 struct buffer_action_entry *entry =
00972 list_entry(node, struct buffer_action_entry, ln);
00973
00974 buffer_action_t *a = entry->action;
00975
00976 int err = buffer_action_private_copy(a, cmp_dobj);
00977 if (err)
00978 return_error(err);
00979 }
00980
00981 return 0;
00982 }
00983
00984 static int buffer_action_multi_to_event(buffer_action_t *action,
00985 struct bless_buffer_event_info *event_info)
00986 {
00987 if (action == NULL || event_info == NULL)
00988 return_error(EINVAL);
00989
00990 event_info->action_type = BLESS_BUFFER_ACTION_MULTI;
00991 event_info->range_start = -1;
00992 event_info->range_length = -1;
00993 event_info->save_fd = -1;
00994
00995 return 0;
00996 }
00997
00998 static int buffer_action_multi_free(buffer_action_t *action)
00999 {
01000 if (action == NULL)
01001 return_error(EINVAL);
01002
01003 struct buffer_action_multi_impl *impl =
01004 (struct buffer_action_multi_impl *) buffer_action_get_impl(action);
01005
01006
01007 struct list_node *node;
01008 struct list_node *tmp;
01009 list_for_each_safe(list_head(impl->action_list)->next, node, tmp) {
01010 struct buffer_action_entry *entry =
01011 list_entry(node, struct buffer_action_entry, ln);
01012
01013 buffer_action_t *a = entry->action;
01014
01015 buffer_action_free(a);
01016 free(entry);
01017 }
01018
01019 free(impl);
01020
01021 return 0;
01022 }
01023