@@ -2,6 +2,7 @@
#include "entry.h"
#include "parallel-checkout.h"
#include "pkt-line.h"
+#include "progress.h"
#include "run-command.h"
#include "streaming.h"
#include "thread-utils.h"
@@ -10,6 +11,8 @@
struct parallel_checkout {
struct checkout_item *items;
size_t nr, alloc;
+ struct progress *progress;
+ unsigned int *progress_cnt;
};
static struct parallel_checkout *parallel_checkout = NULL;
@@ -121,6 +124,22 @@ int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca)
return 0;
}
+size_t pc_queue_size(void)
+{
+ if (!parallel_checkout)
+ return 0;
+ return parallel_checkout->nr;
+}
+
+static void advance_progress_meter(void)
+{
+ if (parallel_checkout && parallel_checkout->progress) {
+ (*parallel_checkout->progress_cnt)++;
+ display_progress(parallel_checkout->progress,
+ *parallel_checkout->progress_cnt);
+ }
+}
+
static int handle_results(struct checkout *state)
{
int ret = 0;
@@ -132,6 +151,10 @@ static int handle_results(struct checkout *state)
struct checkout_item *ci = ¶llel_checkout->items[i];
struct stat *st = &ci->st;
+ /*
+ * Note: progress meter was already incremented for CI_SUCCESS
+ * and CI_FAILED.
+ */
switch(ci->status) {
case CI_SUCCESS:
update_ce_after_write(state, ci->ce, st);
@@ -145,6 +168,7 @@ static int handle_results(struct checkout *state)
* leading dirs in the entry's path.
*/
ret |= checkout_entry_ca(ci->ce, &ci->ca, state, NULL, NULL);
+ advance_progress_meter();
break;
case CI_FAILED:
ret = -1;
@@ -434,6 +458,9 @@ static void parse_and_save_result(const char *line, int len)
*/
if (res->status == CI_SUCCESS)
ci->st = res->st;
+
+ if (res->status != CI_RETRY)
+ advance_progress_meter();
}
static void gather_results_from_workers(struct child_process *workers,
@@ -490,12 +517,17 @@ static void gather_results_from_workers(struct child_process *workers,
static int run_checkout_sequentially(struct checkout *state)
{
size_t i;
- for (i = 0; i < parallel_checkout->nr; ++i)
- write_checkout_item(state, ¶llel_checkout->items[i]);
+ for (i = 0; i < parallel_checkout->nr; ++i) {
+ struct checkout_item *ci = ¶llel_checkout->items[i];
+ write_checkout_item(state, ci);
+ if (ci->status != CI_RETRY)
+ advance_progress_meter();
+ }
return handle_results(state);
}
-int run_parallel_checkout(struct checkout *state, int num_workers, int threshold)
+int run_parallel_checkout(struct checkout *state, int num_workers, int threshold,
+ struct progress *progress, unsigned int *progress_cnt)
{
int ret = 0;
struct child_process *workers;
@@ -508,6 +540,8 @@ int run_parallel_checkout(struct checkout *state, int num_workers, int threshold
num_workers);
pc_status = PC_RUNNING;
+ parallel_checkout->progress = progress;
+ parallel_checkout->progress_cnt = progress_cnt;
if (parallel_checkout->nr == 0) {
goto done;
@@ -27,13 +27,15 @@ void get_parallel_checkout_configs(int *num_workers, int *threshold);
* write and return 0.
*/
int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca);
+size_t pc_queue_size(void);
/*
* Write all the queued entries, returning 0 on success. If the number of
* entries is below the specified threshold, the operation is performed
* sequentially.
*/
-int run_parallel_checkout(struct checkout *state, int num_workers, int threshold);
+int run_parallel_checkout(struct checkout *state, int num_workers, int threshold,
+ struct progress *progress, unsigned int *progress_cnt);
/****************************************************************
* Interface with checkout--helper
@@ -471,17 +471,22 @@ static int check_updates(struct unpack_trees_options *o,
struct cache_entry *ce = index->cache[i];
if (ce->ce_flags & CE_UPDATE) {
+ size_t last_pc_queue_size = pc_queue_size();
+
if (ce->ce_flags & CE_WT_REMOVE)
BUG("both update and delete flags are set on %s",
ce->name);
- display_progress(progress, ++cnt);
ce->ce_flags &= ~CE_UPDATE;
errs |= checkout_entry(ce, &state, NULL, NULL);
+
+ if (last_pc_queue_size == pc_queue_size())
+ display_progress(progress, ++cnt);
}
}
- stop_progress(&progress);
if (pc_workers > 1)
- errs |= run_parallel_checkout(&state, pc_workers, pc_threshold);
+ errs |= run_parallel_checkout(&state, pc_workers, pc_threshold,
+ progress, &cnt);
+ stop_progress(&progress);
errs |= finish_delayed_checkout(&state, NULL);
git_attr_set_direction(GIT_ATTR_CHECKIN);