blob: ad375109ce6ab91fe5b20bda8bc50fc191169215 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "util/progress-updater.h"
#include "common/logging.h"
#include <sstream>
#include "common/names.h"
using namespace impala;
ProgressUpdater::ProgressUpdater() :
logging_level_(2), total_(-1), update_period_(0),
num_complete_(0), last_output_percentage_(0) {
}
void ProgressUpdater::Init(const string& label, int64_t total, int update_period) {
DCHECK_GE(total, 0);
label_ = label;
total_ = total;
update_period_ = update_period;
DCHECK_EQ(num_complete_.Load(), 0) << "Update() should not have been called yet";
DCHECK_EQ(last_output_percentage_.Load(), 0);
}
void ProgressUpdater::Update(int64_t delta) {
DCHECK_GE(total_, 0) << "Init() should have been called already";
DCHECK_GE(delta, 0);
if (delta == 0) return;
num_complete_.Add(delta);
// Cache some shared variables to avoid locking. It's possible the progress
// update is out of order (e.g. prints 1 out of 10 after 2 out of 10)
double old_percentage = last_output_percentage_.Load();
int64_t num_complete = num_complete_.Load();
if (num_complete >= total_) {
// Always print the final 100% complete
VLOG(logging_level_) << label_ << " 100% Complete ("
<< num_complete << " out of " << total_ << ")";
return;
}
// Convert to percentage as int
int new_percentage = (static_cast<double>(num_complete) / total_) * 100;
if (new_percentage - old_percentage > update_period_) {
// Only update shared variable if this guy was the latest.
last_output_percentage_.CompareAndSwap(old_percentage, new_percentage);
VLOG(logging_level_) << label_ << ": " << new_percentage << "% Complete ("
<< num_complete << " out of " << total_ << ")";
}
}
string ProgressUpdater::ToString() const {
stringstream ss;
int64_t num_complete = num_complete_.Load();
if (num_complete >= total_) {
// Always print the final 100% complete
ss << label_ << " 100% Complete (" << num_complete << " out of " << total_ << ")";
return ss.str();
}
int percentage = (static_cast<double>(num_complete) / total_) * 100;
ss << label_ << ": " << percentage << "% Complete ("
<< num_complete << " out of " << total_ << ")";
return ss.str();
}