X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fprocedure.c;h=b237c68b05eae06e38db25d3fdf30162dac75b9c;hb=2bdde1cd21cd58349cf4bd852fddf40524854288;hp=5f3ad2065a4037d2ebda033a6d5b26affcffe76f;hpb=43b1296aafe7582e7dbe6c2b6a8b478d7d9b0fcf;p=pspp-builds.git diff --git a/src/data/procedure.c b/src/data/procedure.c index 5f3ad206..b237c68b 100644 --- a/src/data/procedure.c +++ b/src/data/procedure.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,7 @@ #include #include + struct dataset { /* Cases are read from source, their transformation variables are initialized, @@ -61,6 +63,11 @@ struct dataset { /* Callback which occurs whenever the DICT is replaced by a new one */ replace_dictionary_callback *replace_dict; + /* Callback which occurs whenever the transformation chain(s) have + been modified */ + transformation_change_callback_func *xform_callback; + void *xform_callback_aux; + /* If true, cases are discarded instead of being written to sink. */ bool discard_output; @@ -69,9 +76,9 @@ struct dataset { added to. */ struct trns_chain *cur_trns_chain; - /* The compactor used to compact a case, if necessary; + /* The case map used to compact a case, if necessary; otherwise a null pointer. */ - struct dict_compactor *compactor; + struct case_map *compactor; /* Time at which proc was last invoked. */ time_t last_proc_invocation; @@ -164,11 +171,13 @@ proc_open (struct dataset *ds) /* Prepare sink. */ if (!ds->discard_output) { - ds->compactor = (dict_compacting_would_shrink (ds->permanent_dict) - ? dict_make_compactor (ds->permanent_dict) + struct dictionary *pd = ds->permanent_dict; + size_t compacted_value_cnt = dict_count_values (pd, 1u << DC_SCRATCH); + bool should_compact = compacted_value_cnt < dict_get_next_value_idx (pd); + ds->compactor = (should_compact + ? case_map_to_compact_dict (pd, 1u << DC_SCRATCH) : NULL); - ds->sink = autopaging_writer_create (dict_get_compacted_value_cnt ( - ds->permanent_dict)); + ds->sink = autopaging_writer_create (compacted_value_cnt); } else { @@ -250,10 +259,7 @@ proc_casereader_read (struct casereader *reader UNUSED, void *ds_, { struct ccase tmp; if (ds->compactor != NULL) - { - case_create (&tmp, dict_get_compacted_value_cnt (ds->dict)); - dict_compactor_compact (ds->compactor, &tmp, c); - } + case_map_execute (ds->compactor, c, &tmp); else case_clone (&tmp, c); casewriter_write (ds->sink, &tmp); @@ -318,9 +324,11 @@ proc_commit (struct dataset *ds) /* Finish compacting. */ if (ds->compactor != NULL) { - dict_compactor_destroy (ds->compactor); - dict_compact_values (ds->dict); + case_map_destroy (ds->compactor); ds->compactor = NULL; + + dict_delete_scratch_vars (ds->dict); + dict_compact_values (ds->dict); } /* Old data sink becomes new data source. */ @@ -384,6 +392,10 @@ proc_capture_transformations (struct dataset *ds) assert (ds->temporary_trns_chain == NULL); chain = ds->permanent_trns_chain; ds->cur_trns_chain = ds->permanent_trns_chain = trns_chain_create (); + + if ( ds->xform_callback) + ds->xform_callback (false, ds->xform_callback_aux); + return chain; } @@ -394,6 +406,8 @@ void add_transformation (struct dataset *ds, trns_proc_func *proc, trns_free_func *free, void *aux) { trns_chain_append (ds->cur_trns_chain, NULL, proc, free, aux); + if ( ds->xform_callback) + ds->xform_callback (true, ds->xform_callback_aux); } /* Adds a transformation that processes a case with PROC and @@ -408,6 +422,9 @@ add_transformation_with_finalizer (struct dataset *ds, trns_free_func *free, void *aux) { trns_chain_append (ds->cur_trns_chain, finalize, proc, free, aux); + + if ( ds->xform_callback) + ds->xform_callback (true, ds->xform_callback_aux); } /* Returns the index of the next transformation. @@ -442,6 +459,9 @@ proc_start_temporary_transformations (struct dataset *ds) trns_chain_finalize (ds->permanent_trns_chain); ds->temporary_trns_chain = ds->cur_trns_chain = trns_chain_create (); + + if ( ds->xform_callback) + ds->xform_callback (true, ds->xform_callback_aux); } } @@ -483,6 +503,10 @@ proc_cancel_temporary_transformations (struct dataset *ds) trns_chain_destroy (ds->temporary_trns_chain); ds->temporary_trns_chain = NULL; + if ( ds->xform_callback) + ds->xform_callback (!trns_chain_is_empty (ds->permanent_trns_chain), + ds->xform_callback_aux); + return true; } else @@ -500,23 +524,35 @@ proc_cancel_all_transformations (struct dataset *ds) ok = trns_chain_destroy (ds->temporary_trns_chain) && ok; ds->permanent_trns_chain = ds->cur_trns_chain = trns_chain_create (); ds->temporary_trns_chain = NULL; + if ( ds->xform_callback) + ds->xform_callback (false, ds->xform_callback_aux); + return ok; } /* Initializes procedure handling. */ struct dataset * -create_dataset (replace_source_callback *rps, - replace_dictionary_callback *rds) +create_dataset (transformation_change_callback_func *cb, void *aux) { struct dataset *ds = xzalloc (sizeof(*ds)); ds->dict = dict_create (); ds->caseinit = caseinit_create (); - ds->replace_source = rps; - ds->replace_dict = rds; + ds->xform_callback = cb; + ds->xform_callback_aux = aux; proc_cancel_all_transformations (ds); return ds; } + +void +dataset_add_transform_change_callback (struct dataset *ds, + transformation_change_callback_func *cb, + void *aux) +{ + ds->xform_callback = cb; + ds->xform_callback_aux = aux; +} + /* Finishes up procedure handling. */ void destroy_dataset (struct dataset *ds) @@ -525,6 +561,9 @@ destroy_dataset (struct dataset *ds) dict_destroy (ds->dict); caseinit_destroy (ds->caseinit); trns_chain_destroy (ds->permanent_trns_chain); + + if ( ds->xform_callback) + ds->xform_callback (false, ds->xform_callback_aux); free (ds); } @@ -597,6 +636,18 @@ proc_has_active_file (const struct dataset *ds) return ds->source != NULL; } +/* Returns the active file data source from DS, or a null pointer + if DS has no data source, and removes it from DS. */ +struct casereader * +proc_extract_active_file_data (struct dataset *ds) +{ + struct casereader *reader = ds->source; + ds->source = NULL; + if (ds->replace_source) ds->replace_source (reader); + + return reader; +} + /* Checks whether DS has a corrupted active file. If so, discards it and returns false. If not, returns true without doing anything. */