- client: include precompiled header in rr_sim.cpp so memory

leak detection will work.
    - MGR: Have the BaseFrame call a function to determine if the
        selection list should be saved instead of traversing
        the application pointer.  Each view just overrides the function
        returning a true/false value.  We don't have to worry about null
        pointers and the like.
    - MGR: BOINCGUIApp should never need to know how either the views
        work or the document.  Move the code that determines which
        RPCs should be fired into each of the views.  Have the document
        look for it there.
    - MGR: Reduce duplicate code for hiding and showing an application
    - MGR: Move some Windows and Mac specific code into functions
        and streamline the application startup and shutdown rountines.
    - MGR: Move the event processing that was in BOINCGUIApp into the
        BaseFrame.
    - MGR: General cleanup.
    - MGR: Doxygen comments.
    - MGR: Cleanup some warnings.

    client/
        rr_sim.cpp
    clientgui/
        AdvancedFrame.cpp, .h
        AsyncRPC.cpp, .h
        BOINCBaseFrame.cpp, .h
        BOINCBaseView.cpp, .h
        BOINCClientManager.cpp
        BOINCGUIApp.cpp, .h
        BOINCTaskBar.cpp
        MainDocument.cpp, .h
        sg_BoincSimpleGUI.cpp, .h
        ViewProjects.cpp, .h
        ViewTransfers.cpp, .h
        ViewWork.cpp, .h
        WelcomePage.cpp
    win_build/installerv2/
        BOINC.ism
        BOINCx64.ism
    win_build/
        sim.vcproj

svn path=/trunk/boinc/; revision=16357
This commit is contained in:
Rom Walton 2008-10-29 22:44:55 +00:00
parent 51c993542e
commit 1f1cc48a4c
28 changed files with 1208 additions and 1094 deletions

View File

@ -8850,4 +8850,47 @@ David 29 Oct 2008
client/
client_state.h
cpu_sched.cpp
sim.h
sim.h
Rom 29 Oct 2008
- client: include precompiled header in rr_sim.cpp so memory
leak detection will work.
- MGR: Have the BaseFrame call a function to determine if the
selection list should be saved instead of traversing
the application pointer. Each view just overrides the function
returning a true/false value. We don't have to worry about null
pointers and the like.
- MGR: BOINCGUIApp should never need to know how either the views
work or the document. Move the code that determines which
RPCs should be fired into each of the views. Have the document
look for it there.
- MGR: Reduce duplicate code for hiding and showing an application
- MGR: Move some Windows and Mac specific code into functions
and streamline the application startup and shutdown rountines.
- MGR: Move the event processing that was in BOINCGUIApp into the
BaseFrame.
- MGR: General cleanup.
- MGR: Doxygen comments.
- MGR: Cleanup some warnings.
client/
rr_sim.cpp
clientgui/
AdvancedFrame.cpp, .h
AsyncRPC.cpp, .h
BOINCBaseFrame.cpp, .h
BOINCBaseView.cpp, .h
BOINCClientManager.cpp
BOINCGUIApp.cpp, .h
BOINCTaskBar.cpp
MainDocument.cpp, .h
sg_BoincSimpleGUI.cpp, .h
ViewProjects.cpp, .h
ViewTransfers.cpp, .h
ViewWork.cpp, .h
WelcomePage.cpp
win_build/installerv2/
BOINC.ism
BOINCx64.ism
win_build/
sim.vcproj

View File

@ -1,377 +1,381 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
#ifdef _WIN32
#include "boinc_win.h"
#endif
#ifdef SIM
#include "sim.h"
#else
#include "client_state.h"
#endif
#include "client_msgs.h"
struct RR_SIM_STATUS {
std::vector<RESULT*> active;
COPROCS coprocs;
inline bool can_run(RESULT* rp) {
return coprocs.sufficient_coprocs(
rp->avp->coprocs, log_flags.rr_simulation, "rr_simulation"
);
}
inline void activate(RESULT* rp) {
coprocs.reserve_coprocs(
rp->avp->coprocs, rp, log_flags.rr_simulation, "rr_simulation"
);
active.push_back(rp);
}
// remove *rpbest from active set,
// and adjust CPU time left for other results
//
inline void remove_active(RESULT* rpbest) {
coprocs.free_coprocs(rpbest->avp->coprocs, rpbest, log_flags.rr_simulation, "rr_simulation");
vector<RESULT*>::iterator it = active.begin();
while (it != active.end()) {
RESULT* rp = *it;
if (rp == rpbest) {
it = active.erase(it);
} else {
rp->rrsim_cpu_left -= rp->project->rr_sim_status.proc_rate*rpbest->rrsim_finish_delay;
it++;
}
}
}
inline int nactive() {
return (int) active.size();
}
~RR_SIM_STATUS() {
coprocs.delete_coprocs();
}
};
// Set the project's rrsim_proc_rate:
// the fraction of each CPU that it will get in round-robin mode.
// Precondition: the project's "active" array is populated
//
void PROJECT::set_rrsim_proc_rate(double rrs) {
int nactive = (int)rr_sim_status.active.size();
if (nactive == 0) return;
double x;
if (rrs) {
x = resource_share/rrs;
} else {
x = 1; // pathological case; maybe should be 1/# runnable projects
}
// if this project has fewer active results than CPUs,
// scale up its share to reflect this
//
if (nactive < gstate.ncpus) {
x *= ((double)gstate.ncpus)/nactive;
}
// But its rate on a given CPU can't exceed 1
//
if (x>1) {
x = 1;
}
rr_sim_status.proc_rate = x*gstate.overall_cpu_frac();
if (log_flags.rr_simulation) {
msg_printf(this, MSG_INFO,
"[rr_sim] set_rrsim_proc_rate: %f (rrs %f, rs %f, nactive %d, ocf %f",
rr_sim_status.proc_rate, rrs, resource_share, nactive, gstate.overall_cpu_frac()
);
}
}
void CLIENT_STATE::print_deadline_misses() {
unsigned int i;
RESULT* rp;
PROJECT* p;
for (i=0; i<results.size(); i++){
rp = results[i];
if (rp->rr_sim_misses_deadline && !rp->last_rr_sim_missed_deadline) {
msg_printf(rp->project, MSG_INFO,
"[cpu_sched_debug] Result %s projected to miss deadline.", rp->name
);
}
else if (!rp->rr_sim_misses_deadline && rp->last_rr_sim_missed_deadline) {
msg_printf(rp->project, MSG_INFO,
"[cpu_sched_debug] Result %s projected to meet deadline.", rp->name
);
}
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
if (p->rr_sim_status.deadlines_missed) {
msg_printf(p, MSG_INFO,
"[cpu_sched_debug] Project has %d projected deadline misses",
p->rr_sim_status.deadlines_missed
);
}
}
}
// Do a simulation of the current workload
// with weighted round-robin (WRR) scheduling.
// Include jobs that are downloading.
//
// For efficiency, we simulate a crude approximation of WRR.
// We don't model time-slicing.
// Instead we use a continuous model where, at a given point,
// each project has a set of running jobs that uses all CPUs
// (and obeys coprocessor limits).
// These jobs are assumed to run at a rate proportionate to their avg_ncpus,
// and each project gets CPU proportionate to its RRS.
//
// Outputs are changes to global state:
// For each project p:
// p->rr_sim_deadlines_missed
// p->cpu_shortfall
// For each result r:
// r->rr_sim_misses_deadline
// r->last_rr_sim_missed_deadline
// gstate.cpu_shortfall
//
// Deadline misses are not counted for tasks
// that are too large to run in RAM right now.
//
void CLIENT_STATE::rr_simulation() {
double rrs = nearly_runnable_resource_share();
double trs = total_resource_share();
PROJECT* p, *pbest;
RESULT* rp, *rpbest;
RR_SIM_STATUS sim_status;
unsigned int i;
sim_status.coprocs.clone(coprocs, false);
double ar = available_ram();
if (log_flags.rr_simulation) {
msg_printf(0, MSG_INFO,
"[rr_sim] rr_sim start: work_buf_total %f rrs %f trs %f ncpus %d",
work_buf_total(), rrs, trs, ncpus
);
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
p->rr_sim_status.clear();
}
// Decide what jobs to include in the simulation,
// and pick the ones that are initially running
//
for (i=0; i<results.size(); i++) {
rp = results[i];
if (!rp->nearly_runnable()) continue;
if (rp->some_download_stalled()) continue;
if (rp->project->non_cpu_intensive) continue;
rp->rrsim_cpu_left = rp->estimated_cpu_time_remaining(false);
p = rp->project;
if (p->rr_sim_status.can_run(rp, gstate.ncpus) && sim_status.can_run(rp)) {
sim_status.activate(rp);
p->rr_sim_status.activate(rp);
} else {
p->rr_sim_status.add_pending(rp);
}
rp->last_rr_sim_missed_deadline = rp->rr_sim_misses_deadline;
rp->rr_sim_misses_deadline = false;
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
p->set_rrsim_proc_rate(rrs);
// if there are no results for a project,
// the shortfall is its entire share.
//
if (p->rr_sim_status.none_active()) {
double rsf = trs ? p->resource_share/trs : 1;
p->rr_sim_status.cpu_shortfall = work_buf_total() * overall_cpu_frac() * ncpus * rsf;
if (log_flags.rr_simulation) {
msg_printf(p, MSG_INFO,
"[rr_sim] no results; shortfall %f wbt %f ocf %f rsf %f",
p->rr_sim_status.cpu_shortfall, work_buf_total(), overall_cpu_frac(), rsf
);
}
}
}
double buf_end = now + work_buf_total();
// Simulation loop. Keep going until work done
//
double sim_now = now;
cpu_shortfall = 0;
while (sim_status.nactive()) {
// compute finish times and see which result finishes first
//
rpbest = NULL;
for (i=0; i<sim_status.active.size(); i++) {
rp = sim_status.active[i];
p = rp->project;
rp->rrsim_finish_delay = rp->rrsim_cpu_left/p->rr_sim_status.proc_rate;
if (!rpbest || rp->rrsim_finish_delay < rpbest->rrsim_finish_delay) {
rpbest = rp;
}
}
pbest = rpbest->project;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] result %s finishes after %f (%f/%f)",
rpbest->name, rpbest->rrsim_finish_delay,
rpbest->rrsim_cpu_left, pbest->rr_sim_status.proc_rate
);
}
// "rpbest" is first result to finish. Does it miss its deadline?
//
double diff = sim_now + rpbest->rrsim_finish_delay - ((rpbest->computation_deadline()-now)*CPU_PESSIMISM_FACTOR + now);
if (diff > 0) {
ACTIVE_TASK* atp = lookup_active_task_by_result(rpbest);
if (atp && atp->procinfo.working_set_size_smoothed > ar) {
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] result %s misses deadline but too large to run",
rpbest->name
);
}
} else {
rpbest->rr_sim_misses_deadline = true;
pbest->rr_sim_status.deadlines_missed++;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] result %s misses deadline by %f",
rpbest->name, diff
);
}
}
}
int last_active_size = sim_status.nactive();
int last_proj_active_size = pbest->rr_sim_status.cpus_used();
sim_status.remove_active(rpbest);
pbest->rr_sim_status.remove_active(rpbest);
// If project has more results, add one or more to active set.
//
while (1) {
rp = pbest->rr_sim_status.get_pending();
if (!rp) break;
if (pbest->rr_sim_status.can_run(rp, gstate.ncpus) && sim_status.can_run(rp)) {
sim_status.activate(rp);
pbest->rr_sim_status.activate(rp);
} else {
pbest->rr_sim_status.add_pending(rp);
break;
}
}
// If all work done for a project, subtract that project's share
// and recompute processing rates
//
if (pbest->rr_sim_status.none_active()) {
rrs -= pbest->resource_share;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] decr rrs by %f, new value %f",
pbest->resource_share, rrs
);
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
p->set_rrsim_proc_rate(rrs);
}
}
// increment CPU shortfalls if necessary
//
if (sim_now < buf_end) {
double end_time = sim_now + rpbest->rrsim_finish_delay;
if (end_time > buf_end) end_time = buf_end;
double d_time = end_time - sim_now;
int nidle_cpus = ncpus - last_active_size;
if (nidle_cpus<0) nidle_cpus = 0;
if (nidle_cpus > 0) cpu_shortfall += d_time*nidle_cpus;
double rsf = trs?pbest->resource_share/trs:1;
double proj_cpu_share = ncpus*rsf;
if (last_proj_active_size < proj_cpu_share) {
pbest->rr_sim_status.cpu_shortfall += d_time*(proj_cpu_share - last_proj_active_size);
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] new shortfall %f d_time %f proj_cpu_share %f lpas %d",
pbest->rr_sim_status.cpu_shortfall, d_time, proj_cpu_share, last_proj_active_size
);
}
}
if (end_time < buf_end) {
d_time = buf_end - end_time;
// if this is the last result for this project, account for the tail
if (pbest->rr_sim_status.none_active()) {
pbest->rr_sim_status.cpu_shortfall += d_time * proj_cpu_share;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO, "[rr_sim] proj out of work; shortfall %f d %f pcs %f",
pbest->rr_sim_status.cpu_shortfall, d_time, proj_cpu_share
);
}
}
}
if (log_flags.rr_simulation) {
msg_printf(0, MSG_INFO,
"[rr_sim] total: idle cpus %d, last active %d, active %d, shortfall %f",
nidle_cpus, last_active_size, sim_status.nactive(),
cpu_shortfall
);
msg_printf(0, MSG_INFO,
"[rr_sim] proj %s: last active %d, active %d, shortfall %f",
pbest->get_project_name(), last_proj_active_size,
pbest->rr_sim_status.cpus_used(),
pbest->rr_sim_status.cpu_shortfall
);
}
}
sim_now += rpbest->rrsim_finish_delay;
}
if (sim_now < buf_end) {
cpu_shortfall += (buf_end - sim_now) * ncpus;
}
if (log_flags.rr_simulation) {
for (i=0; i<projects.size(); i++) {
p = projects[i];
if (p->rr_sim_status.cpu_shortfall) {
msg_printf(p, MSG_INFO,
"[rr_sim] shortfall %f\n", p->rr_sim_status.cpu_shortfall
);
}
}
msg_printf(NULL, MSG_INFO,
"[rr_sim] done; total shortfall %f\n",
cpu_shortfall
);
}
}
#endif
#include "client_msgs.h"
struct RR_SIM_STATUS {
std::vector<RESULT*> active;
COPROCS coprocs;
inline bool can_run(RESULT* rp) {
return coprocs.sufficient_coprocs(
rp->avp->coprocs, log_flags.rr_simulation, "rr_simulation"
);
}
inline void activate(RESULT* rp) {
coprocs.reserve_coprocs(
rp->avp->coprocs, rp, log_flags.rr_simulation, "rr_simulation"
);
active.push_back(rp);
}
// remove *rpbest from active set,
// and adjust CPU time left for other results
//
inline void remove_active(RESULT* rpbest) {
coprocs.free_coprocs(rpbest->avp->coprocs, rpbest, log_flags.rr_simulation, "rr_simulation");
vector<RESULT*>::iterator it = active.begin();
while (it != active.end()) {
RESULT* rp = *it;
if (rp == rpbest) {
it = active.erase(it);
} else {
rp->rrsim_cpu_left -= rp->project->rr_sim_status.proc_rate*rpbest->rrsim_finish_delay;
it++;
}
}
}
inline int nactive() {
return (int) active.size();
}
~RR_SIM_STATUS() {
coprocs.delete_coprocs();
}
};
// Set the project's rrsim_proc_rate:
// the fraction of each CPU that it will get in round-robin mode.
// Precondition: the project's "active" array is populated
//
void PROJECT::set_rrsim_proc_rate(double rrs) {
int nactive = (int)rr_sim_status.active.size();
if (nactive == 0) return;
double x;
if (rrs) {
x = resource_share/rrs;
} else {
x = 1; // pathological case; maybe should be 1/# runnable projects
}
// if this project has fewer active results than CPUs,
// scale up its share to reflect this
//
if (nactive < gstate.ncpus) {
x *= ((double)gstate.ncpus)/nactive;
}
// But its rate on a given CPU can't exceed 1
//
if (x>1) {
x = 1;
}
rr_sim_status.proc_rate = x*gstate.overall_cpu_frac();
if (log_flags.rr_simulation) {
msg_printf(this, MSG_INFO,
"[rr_sim] set_rrsim_proc_rate: %f (rrs %f, rs %f, nactive %d, ocf %f",
rr_sim_status.proc_rate, rrs, resource_share, nactive, gstate.overall_cpu_frac()
);
}
}
void CLIENT_STATE::print_deadline_misses() {
unsigned int i;
RESULT* rp;
PROJECT* p;
for (i=0; i<results.size(); i++){
rp = results[i];
if (rp->rr_sim_misses_deadline && !rp->last_rr_sim_missed_deadline) {
msg_printf(rp->project, MSG_INFO,
"[cpu_sched_debug] Result %s projected to miss deadline.", rp->name
);
}
else if (!rp->rr_sim_misses_deadline && rp->last_rr_sim_missed_deadline) {
msg_printf(rp->project, MSG_INFO,
"[cpu_sched_debug] Result %s projected to meet deadline.", rp->name
);
}
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
if (p->rr_sim_status.deadlines_missed) {
msg_printf(p, MSG_INFO,
"[cpu_sched_debug] Project has %d projected deadline misses",
p->rr_sim_status.deadlines_missed
);
}
}
}
// Do a simulation of the current workload
// with weighted round-robin (WRR) scheduling.
// Include jobs that are downloading.
//
// For efficiency, we simulate a crude approximation of WRR.
// We don't model time-slicing.
// Instead we use a continuous model where, at a given point,
// each project has a set of running jobs that uses all CPUs
// (and obeys coprocessor limits).
// These jobs are assumed to run at a rate proportionate to their avg_ncpus,
// and each project gets CPU proportionate to its RRS.
//
// Outputs are changes to global state:
// For each project p:
// p->rr_sim_deadlines_missed
// p->cpu_shortfall
// For each result r:
// r->rr_sim_misses_deadline
// r->last_rr_sim_missed_deadline
// gstate.cpu_shortfall
//
// Deadline misses are not counted for tasks
// that are too large to run in RAM right now.
//
void CLIENT_STATE::rr_simulation() {
double rrs = nearly_runnable_resource_share();
double trs = total_resource_share();
PROJECT* p, *pbest;
RESULT* rp, *rpbest;
RR_SIM_STATUS sim_status;
unsigned int i;
sim_status.coprocs.clone(coprocs, false);
double ar = available_ram();
if (log_flags.rr_simulation) {
msg_printf(0, MSG_INFO,
"[rr_sim] rr_sim start: work_buf_total %f rrs %f trs %f ncpus %d",
work_buf_total(), rrs, trs, ncpus
);
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
p->rr_sim_status.clear();
}
// Decide what jobs to include in the simulation,
// and pick the ones that are initially running
//
for (i=0; i<results.size(); i++) {
rp = results[i];
if (!rp->nearly_runnable()) continue;
if (rp->some_download_stalled()) continue;
if (rp->project->non_cpu_intensive) continue;
rp->rrsim_cpu_left = rp->estimated_cpu_time_remaining(false);
p = rp->project;
if (p->rr_sim_status.can_run(rp, gstate.ncpus) && sim_status.can_run(rp)) {
sim_status.activate(rp);
p->rr_sim_status.activate(rp);
} else {
p->rr_sim_status.add_pending(rp);
}
rp->last_rr_sim_missed_deadline = rp->rr_sim_misses_deadline;
rp->rr_sim_misses_deadline = false;
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
p->set_rrsim_proc_rate(rrs);
// if there are no results for a project,
// the shortfall is its entire share.
//
if (p->rr_sim_status.none_active()) {
double rsf = trs ? p->resource_share/trs : 1;
p->rr_sim_status.cpu_shortfall = work_buf_total() * overall_cpu_frac() * ncpus * rsf;
if (log_flags.rr_simulation) {
msg_printf(p, MSG_INFO,
"[rr_sim] no results; shortfall %f wbt %f ocf %f rsf %f",
p->rr_sim_status.cpu_shortfall, work_buf_total(), overall_cpu_frac(), rsf
);
}
}
}
double buf_end = now + work_buf_total();
// Simulation loop. Keep going until work done
//
double sim_now = now;
cpu_shortfall = 0;
while (sim_status.nactive()) {
// compute finish times and see which result finishes first
//
rpbest = NULL;
for (i=0; i<sim_status.active.size(); i++) {
rp = sim_status.active[i];
p = rp->project;
rp->rrsim_finish_delay = rp->rrsim_cpu_left/p->rr_sim_status.proc_rate;
if (!rpbest || rp->rrsim_finish_delay < rpbest->rrsim_finish_delay) {
rpbest = rp;
}
}
pbest = rpbest->project;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] result %s finishes after %f (%f/%f)",
rpbest->name, rpbest->rrsim_finish_delay,
rpbest->rrsim_cpu_left, pbest->rr_sim_status.proc_rate
);
}
// "rpbest" is first result to finish. Does it miss its deadline?
//
double diff = sim_now + rpbest->rrsim_finish_delay - ((rpbest->computation_deadline()-now)*CPU_PESSIMISM_FACTOR + now);
if (diff > 0) {
ACTIVE_TASK* atp = lookup_active_task_by_result(rpbest);
if (atp && atp->procinfo.working_set_size_smoothed > ar) {
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] result %s misses deadline but too large to run",
rpbest->name
);
}
} else {
rpbest->rr_sim_misses_deadline = true;
pbest->rr_sim_status.deadlines_missed++;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] result %s misses deadline by %f",
rpbest->name, diff
);
}
}
}
int last_active_size = sim_status.nactive();
int last_proj_active_size = pbest->rr_sim_status.cpus_used();
sim_status.remove_active(rpbest);
pbest->rr_sim_status.remove_active(rpbest);
// If project has more results, add one or more to active set.
//
while (1) {
rp = pbest->rr_sim_status.get_pending();
if (!rp) break;
if (pbest->rr_sim_status.can_run(rp, gstate.ncpus) && sim_status.can_run(rp)) {
sim_status.activate(rp);
pbest->rr_sim_status.activate(rp);
} else {
pbest->rr_sim_status.add_pending(rp);
break;
}
}
// If all work done for a project, subtract that project's share
// and recompute processing rates
//
if (pbest->rr_sim_status.none_active()) {
rrs -= pbest->resource_share;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] decr rrs by %f, new value %f",
pbest->resource_share, rrs
);
}
for (i=0; i<projects.size(); i++) {
p = projects[i];
p->set_rrsim_proc_rate(rrs);
}
}
// increment CPU shortfalls if necessary
//
if (sim_now < buf_end) {
double end_time = sim_now + rpbest->rrsim_finish_delay;
if (end_time > buf_end) end_time = buf_end;
double d_time = end_time - sim_now;
int nidle_cpus = ncpus - last_active_size;
if (nidle_cpus<0) nidle_cpus = 0;
if (nidle_cpus > 0) cpu_shortfall += d_time*nidle_cpus;
double rsf = trs?pbest->resource_share/trs:1;
double proj_cpu_share = ncpus*rsf;
if (last_proj_active_size < proj_cpu_share) {
pbest->rr_sim_status.cpu_shortfall += d_time*(proj_cpu_share - last_proj_active_size);
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO,
"[rr_sim] new shortfall %f d_time %f proj_cpu_share %f lpas %d",
pbest->rr_sim_status.cpu_shortfall, d_time, proj_cpu_share, last_proj_active_size
);
}
}
if (end_time < buf_end) {
d_time = buf_end - end_time;
// if this is the last result for this project, account for the tail
if (pbest->rr_sim_status.none_active()) {
pbest->rr_sim_status.cpu_shortfall += d_time * proj_cpu_share;
if (log_flags.rr_simulation) {
msg_printf(pbest, MSG_INFO, "[rr_sim] proj out of work; shortfall %f d %f pcs %f",
pbest->rr_sim_status.cpu_shortfall, d_time, proj_cpu_share
);
}
}
}
if (log_flags.rr_simulation) {
msg_printf(0, MSG_INFO,
"[rr_sim] total: idle cpus %d, last active %d, active %d, shortfall %f",
nidle_cpus, last_active_size, sim_status.nactive(),
cpu_shortfall
);
msg_printf(0, MSG_INFO,
"[rr_sim] proj %s: last active %d, active %d, shortfall %f",
pbest->get_project_name(), last_proj_active_size,
pbest->rr_sim_status.cpus_used(),
pbest->rr_sim_status.cpu_shortfall
);
}
}
sim_now += rpbest->rrsim_finish_delay;
}
if (sim_now < buf_end) {
cpu_shortfall += (buf_end - sim_now) * ncpus;
}
if (log_flags.rr_simulation) {
for (i=0; i<projects.size(); i++) {
p = projects[i];
if (p->rr_sim_status.cpu_shortfall) {
msg_printf(p, MSG_INFO,
"[rr_sim] shortfall %f\n", p->rr_sim_status.cpu_shortfall
);
}
}
msg_printf(NULL, MSG_INFO,
"[rr_sim] done; total shortfall %f\n",
cpu_shortfall
);
}
}

View File

@ -1034,6 +1034,25 @@ void CAdvancedFrame::RestoreWindowDimensions() {
}
int CAdvancedFrame::_GetCurrentViewPage() {
switch (m_pNotebook->GetSelection()) {
case 0:
return VW_PROJ;
case 1:
return VW_TASK;
case 2:
return VW_XFER;
case 3:
return VW_MSGS;
case 4:
return VW_STAT;
case 5:
return VW_DISK;
}
return 0; // Should never happen.
}
void CAdvancedFrame::OnActivitySelection(wxCommandEvent& event) {
wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnActivitySelection - Function Begin"));
@ -1135,11 +1154,11 @@ void CAdvancedFrame::OnSelectComputer(wxCommandEvent& WXUNUSED(event)) {
// Connect to the remote machine
wxString sHost = dlg.m_ComputerNameCtrl->GetValue();
long lPort = GUI_RPC_PORT;
int iPos = sHost.find(_(":"));
size_t iPos = sHost.find(_(":"));
if (iPos != wxNOT_FOUND) {
wxString sPort = sHost.substr((size_t)iPos + 1);
wxString sPort = sHost.substr(iPos + 1);
if (!sPort.ToLong(&lPort)) lPort = GUI_RPC_PORT;
sHost.erase((size_t)iPos);
sHost.erase(iPos);
}
lRetVal = pDoc->Connect(
sHost,

View File

@ -23,6 +23,18 @@
#pragma interface "AdvancedFrame.cpp"
#endif
///
/// Bitmask values for CMainDocument::RunPeriodicRPCs()
///
#define VW_PROJ 1
#define VW_TASK 2
#define VW_XFER 4
#define VW_MSGS 8
#define VW_STAT 16
#define VW_DISK 32
class CStatusBar : public wxStatusBar
{
DECLARE_DYNAMIC_CLASS(CStatusBar)
@ -83,7 +95,6 @@ public:
void OnFrameRender( wxTimerEvent& event );
void OnNotebookSelectionChanged( wxNotebookEvent& event );
int GetViewTabIndex() { return m_pNotebook->GetSelection(); }
void OnRefreshView( CFrameEvent& event );
void OnConnect( CFrameEvent& event );
@ -94,6 +105,13 @@ public:
wxTimer* m_pRefreshStateTimer;
wxTimer* m_pFrameRenderTimer;
protected:
virtual int _GetCurrentViewPage();
wxAcceleratorEntry m_Shortcuts[1]; // For HELP keyboard shortcut
wxAcceleratorTable* m_pAccelTable;
private:
wxMenuBar* m_pMenubar;
@ -131,13 +149,6 @@ private:
void StartTimers();
void StopTimers();
#ifdef __WXMAC__
protected:
wxAcceleratorEntry m_Shortcuts[1]; // For HELP keyboard shortcut
wxAcceleratorTable* m_pAccelTable;
#endif
DECLARE_EVENT_TABLE()
};

View File

@ -72,7 +72,7 @@ bool ASYNC_RPC_REQUEST::isSameAs(ASYNC_RPC_REQUEST& otherRequest) {
AsyncRPC::AsyncRPC(CMainDocument *pDoc) {
m_Doc = pDoc;
m_pDoc = pDoc;
}
@ -92,20 +92,19 @@ int AsyncRPC::RPC_Wait(RPC_SELECTOR which_rpc, void *arg1, void *arg2,
request.arg4 = arg4;
request.rpcType = RPC_TYPE_WAIT_FOR_COMPLETION;
retval = m_Doc->RequestRPC(request, hasPriority);
retval = m_pDoc->RequestRPC(request, hasPriority);
return retval;
}
RPCThread::RPCThread(CMainDocument *pDoc)
: wxThread() {
m_Doc = pDoc;
RPCThread::RPCThread(CMainDocument *pDoc) : wxThread() {
m_pDoc = pDoc;
}
void RPCThread::OnExit() {
// Tell CMainDocument that thread has gracefully ended
m_Doc->m_RPCThread = NULL;
m_pDoc->m_RPCThread = NULL;
}
@ -117,14 +116,13 @@ void RPCThread::OnExit() {
void *RPCThread::Entry() {
int retval;
CRPCFinishedEvent RPC_done_event( wxEVT_RPC_FINISHED );
while(true) {
// check if we were asked to exit
if ( TestDestroy() )
break;
if (! m_Doc->GetCurrentRPCRequest()->isActive) {
if (! m_pDoc->GetCurrentRPCRequest()->isActive) {
// Wait until CMainDocument issues next RPC request
#ifdef __WXMSW__ // Until we can suspend the thread without Deadlock on Windows
Sleep(1);
@ -134,20 +132,24 @@ void *RPCThread::Entry() {
continue;
}
if (! m_Doc->IsConnected()) {
if (! m_pDoc->IsConnected()) {
Yield();
}
retval = ProcessRPCRequest();
wxPostEvent( wxTheApp, RPC_done_event );
CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
if (pFrame) {
pFrame->FireRPCFinished();
}
}
#ifndef __WXMSW__ // Deadlocks on Windows
// Use a critical section to prevent a crash during
// manager shutdown due to a rare race condition
m_Doc->m_critsect.Enter();
m_Doc->m_critsect.Leave();
m_pDoc->m_critsect.Enter();
m_pDoc->m_critsect.Leave();
#endif // !!__WXMSW__ // Deadlocks on Windows
@ -159,7 +161,7 @@ int RPCThread::ProcessRPCRequest() {
int retval = 0;
ASYNC_RPC_REQUEST *current_request;
current_request = m_Doc->GetCurrentRPCRequest();
current_request = m_pDoc->GetCurrentRPCRequest();
switch (current_request->which_rpc) {
// RPC_SELECTORS with no arguments
case RPC_RUN_BENCHMARKS:
@ -179,45 +181,45 @@ int RPCThread::ProcessRPCRequest() {
}
switch (current_request->which_rpc) {
case RPC_AUTHORIZE:
retval = (m_Doc->rpcClient).authorize((const char*)(current_request->arg1));
retval = (m_pDoc->rpcClient).authorize((const char*)(current_request->arg1));
break;
case RPC_EXCHANGE_VERSIONS:
retval = (m_Doc->rpcClient).exchange_versions(*(VERSION_INFO*)(current_request->arg1));
retval = (m_pDoc->rpcClient).exchange_versions(*(VERSION_INFO*)(current_request->arg1));
break;
case RPC_GET_STATE:
retval = (m_Doc->rpcClient).get_state(*(CC_STATE*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_state(*(CC_STATE*)(current_request->arg1));
break;
case RPC_GET_RESULTS:
retval = (m_Doc->rpcClient).get_results(*(RESULTS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_results(*(RESULTS*)(current_request->arg1));
break;
case RPC_GET_FILE_TRANSFERS:
retval = (m_Doc->rpcClient).get_file_transfers(*(FILE_TRANSFERS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_file_transfers(*(FILE_TRANSFERS*)(current_request->arg1));
break;
case RPC_GET_SIMPLE_GUI_INFO1:
retval = (m_Doc->rpcClient).get_simple_gui_info(*(SIMPLE_GUI_INFO*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_simple_gui_info(*(SIMPLE_GUI_INFO*)(current_request->arg1));
break;
case RPC_GET_SIMPLE_GUI_INFO2:
// RPC_GET_SIMPLE_GUI_INFO2 is equivalent to doing both
// RPC_GET_PROJECT_STATUS1 and RPC_GET_RESULTS
retval = (m_Doc->rpcClient).get_results(*(RESULTS*)(current_request->arg3));
retval = (m_pDoc->rpcClient).get_results(*(RESULTS*)(current_request->arg3));
if (!retval) {
retval = (m_Doc->rpcClient).get_project_status(*(PROJECTS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_project_status(*(PROJECTS*)(current_request->arg1));
}
break;
case RPC_GET_PROJECT_STATUS1:
retval = (m_Doc->rpcClient).get_project_status(*(PROJECTS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_project_status(*(PROJECTS*)(current_request->arg1));
break;
case RPC_GET_PROJECT_STATUS2:
retval = (m_Doc->rpcClient).get_project_status(*(PROJECTS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_project_status(*(PROJECTS*)(current_request->arg1));
break;
case RPC_GET_ALL_PROJECTS_LIST:
retval = (m_Doc->rpcClient).get_all_projects_list(*(ALL_PROJECTS_LIST*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_all_projects_list(*(ALL_PROJECTS_LIST*)(current_request->arg1));
break;
case RPC_GET_DISK_USAGE:
retval = (m_Doc->rpcClient).get_disk_usage(*(DISK_USAGE*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_disk_usage(*(DISK_USAGE*)(current_request->arg1));
break;
case RPC_SHOW_GRAPHICS:
retval = (m_Doc->rpcClient).show_graphics(
retval = (m_pDoc->rpcClient).show_graphics(
(const char*)(current_request->arg1),
(const char*)(current_request->arg2),
*(int*)(current_request->arg3),
@ -225,107 +227,107 @@ int RPCThread::ProcessRPCRequest() {
);
break;
case RPC_PROJECT_OP:
retval = (m_Doc->rpcClient).project_op(
retval = (m_pDoc->rpcClient).project_op(
*(PROJECT*)(current_request->arg1),
(const char*)(current_request->arg2)
);
break;
case RPC_SET_RUN_MODE:
retval = (m_Doc->rpcClient).set_run_mode(
retval = (m_pDoc->rpcClient).set_run_mode(
*(int*)(current_request->arg1),
*(double*)(current_request->arg2)
);
break;
case RPC_SET_NETWORK_MODE:
retval = (m_Doc->rpcClient).set_network_mode(
retval = (m_pDoc->rpcClient).set_network_mode(
*(int*)(current_request->arg1),
*(double*)(current_request->arg2)
);
break;
case RPC_GET_SCREENSAVER_TASKS:
retval = (m_Doc->rpcClient).get_screensaver_tasks(
retval = (m_pDoc->rpcClient).get_screensaver_tasks(
*(int*)(current_request->arg1),
*(RESULTS*)(current_request->arg2)
);
break;
case RPC_RUN_BENCHMARKS:
retval = (m_Doc->rpcClient).run_benchmarks();
retval = (m_pDoc->rpcClient).run_benchmarks();
break;
case RPC_SET_PROXY_SETTINGS:
retval = (m_Doc->rpcClient).set_proxy_settings(*(GR_PROXY_INFO*)(current_request->arg1));
retval = (m_pDoc->rpcClient).set_proxy_settings(*(GR_PROXY_INFO*)(current_request->arg1));
break;
case RPC_GET_PROXY_SETTINGS:
retval = (m_Doc->rpcClient).get_proxy_settings(*(GR_PROXY_INFO*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_proxy_settings(*(GR_PROXY_INFO*)(current_request->arg1));
break;
case RPC_GET_MESSAGES:
retval = (m_Doc->rpcClient).get_messages(
retval = (m_pDoc->rpcClient).get_messages(
*(int*)(current_request->arg1),
*(MESSAGES*)(current_request->arg2)
);
break;
case RPC_FILE_TRANSFER_OP:
retval = (m_Doc->rpcClient).file_transfer_op(
retval = (m_pDoc->rpcClient).file_transfer_op(
*(FILE_TRANSFER*)(current_request->arg1),
(const char*)(current_request->arg2)
);
break;
case RPC_RESULT_OP:
retval = (m_Doc->rpcClient).result_op(
retval = (m_pDoc->rpcClient).result_op(
*(RESULT*)(current_request->arg1),
(const char*)(current_request->arg2)
);
break;
case RPC_GET_HOST_INFO:
retval = (m_Doc->rpcClient).get_host_info(*(HOST_INFO*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_host_info(*(HOST_INFO*)(current_request->arg1));
break;
case RPC_QUIT:
retval = (m_Doc->rpcClient).quit();
retval = (m_pDoc->rpcClient).quit();
break;
case RPC_ACCT_MGR_INFO:
retval = (m_Doc->rpcClient).acct_mgr_info(*(ACCT_MGR_INFO*)(current_request->arg1));
retval = (m_pDoc->rpcClient).acct_mgr_info(*(ACCT_MGR_INFO*)(current_request->arg1));
break;
case RPC_GET_STATISTICS:
retval = (m_Doc->rpcClient).get_statistics(*(PROJECTS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_statistics(*(PROJECTS*)(current_request->arg1));
break;
case RPC_NETWORK_AVAILABLE:
retval = (m_Doc->rpcClient).network_available();
retval = (m_pDoc->rpcClient).network_available();
break;
case RPC_GET_PROJECT_INIT_STATUS:
retval = (m_Doc->rpcClient).get_project_init_status(*(PROJECT_INIT_STATUS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_project_init_status(*(PROJECT_INIT_STATUS*)(current_request->arg1));
break;
case RPC_GET_PROJECT_CONFIG:
retval = (m_Doc->rpcClient).get_project_config(*(std::string*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_project_config(*(std::string*)(current_request->arg1));
break;
case RPC_GET_PROJECT_CONFIG_POLL:
retval = (m_Doc->rpcClient).get_project_config_poll(*(PROJECT_CONFIG*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_project_config_poll(*(PROJECT_CONFIG*)(current_request->arg1));
break;
case RPC_LOOKUP_ACCOUNT:
retval = (m_Doc->rpcClient).lookup_account(*(ACCOUNT_IN*)(current_request->arg1));
retval = (m_pDoc->rpcClient).lookup_account(*(ACCOUNT_IN*)(current_request->arg1));
break;
case RPC_LOOKUP_ACCOUNT_POLL:
retval = (m_Doc->rpcClient).lookup_account_poll(*(ACCOUNT_OUT*)(current_request->arg1));
retval = (m_pDoc->rpcClient).lookup_account_poll(*(ACCOUNT_OUT*)(current_request->arg1));
break;
case RPC_CREATE_ACCOUNT:
retval = (m_Doc->rpcClient).create_account(*(ACCOUNT_IN*)(current_request->arg1));
retval = (m_pDoc->rpcClient).create_account(*(ACCOUNT_IN*)(current_request->arg1));
break;
case RPC_CREATE_ACCOUNT_POLL:
retval = (m_Doc->rpcClient).create_account_poll(*(ACCOUNT_OUT*)(current_request->arg1));
retval = (m_pDoc->rpcClient).create_account_poll(*(ACCOUNT_OUT*)(current_request->arg1));
break;
case RPC_PROJECT_ATTACH:
retval = (m_Doc->rpcClient).project_attach(
retval = (m_pDoc->rpcClient).project_attach(
(const char*)(current_request->arg1),
(const char*)(current_request->arg2),
(const char*)(current_request->arg3)
);
break;
case RPC_PROJECT_ATTACH_FROM_FILE:
retval = (m_Doc->rpcClient).project_attach_from_file();
retval = (m_pDoc->rpcClient).project_attach_from_file();
break;
case RPC_PROJECT_ATTACH_POLL:
retval = (m_Doc->rpcClient).project_attach_poll(*(PROJECT_ATTACH_REPLY*)(current_request->arg1));
retval = (m_pDoc->rpcClient).project_attach_poll(*(PROJECT_ATTACH_REPLY*)(current_request->arg1));
break;
case RPC_ACCT_MGR_RPC:
retval = (m_Doc->rpcClient).acct_mgr_rpc(
retval = (m_pDoc->rpcClient).acct_mgr_rpc(
(const char*)(current_request->arg1),
(const char*)(current_request->arg2),
(const char*)(current_request->arg3),
@ -333,52 +335,52 @@ int RPCThread::ProcessRPCRequest() {
);
break;
case RPC_ACCT_MGR_RPC_POLL:
retval = (m_Doc->rpcClient).acct_mgr_rpc_poll(*(ACCT_MGR_RPC_REPLY*)(current_request->arg1));
retval = (m_pDoc->rpcClient).acct_mgr_rpc_poll(*(ACCT_MGR_RPC_REPLY*)(current_request->arg1));
break;
case RPC_GET_NEWER_VERSION:
retval = (m_Doc->rpcClient).get_newer_version(*(std::string*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_newer_version(*(std::string*)(current_request->arg1));
break;
case RPC_READ_GLOBAL_PREFS_OVERRIDE:
retval = (m_Doc->rpcClient).read_global_prefs_override();
retval = (m_pDoc->rpcClient).read_global_prefs_override();
break;
case RPC_READ_CC_CONFIG:
retval = (m_Doc->rpcClient).read_cc_config();
retval = (m_pDoc->rpcClient).read_cc_config();
break;
case RPC_GET_CC_STATUS:
retval = (m_Doc->rpcClient).get_cc_status(*(CC_STATUS*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_cc_status(*(CC_STATUS*)(current_request->arg1));
break;
case RPC_GET_GLOBAL_PREFS_FILE:
retval = (m_Doc->rpcClient).get_global_prefs_file(*(std::string*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_global_prefs_file(*(std::string*)(current_request->arg1));
break;
case RPC_GET_GLOBAL_PREFS_WORKING:
retval = (m_Doc->rpcClient).get_global_prefs_working(*(std::string*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_global_prefs_working(*(std::string*)(current_request->arg1));
break;
case RPC_GET_GLOBAL_PREFS_WORKING_STRUCT:
retval = (m_Doc->rpcClient).get_global_prefs_working_struct(
retval = (m_pDoc->rpcClient).get_global_prefs_working_struct(
*(GLOBAL_PREFS*)(current_request->arg1),
*(GLOBAL_PREFS_MASK*)(current_request->arg2)
);
break;
case RPC_GET_GLOBAL_PREFS_OVERRIDE:
retval = (m_Doc->rpcClient).get_global_prefs_override(*(std::string*)(current_request->arg1));
retval = (m_pDoc->rpcClient).get_global_prefs_override(*(std::string*)(current_request->arg1));
break;
case RPC_SET_GLOBAL_PREFS_OVERRIDE:
retval = (m_Doc->rpcClient).set_global_prefs_override(*(std::string*)(current_request->arg1));
retval = (m_pDoc->rpcClient).set_global_prefs_override(*(std::string*)(current_request->arg1));
break;
case RPC_GET_GLOBAL_PREFS_OVERRIDE_STRUCT:
retval = (m_Doc->rpcClient).get_global_prefs_override_struct(
retval = (m_pDoc->rpcClient).get_global_prefs_override_struct(
*(GLOBAL_PREFS*)(current_request->arg1),
*(GLOBAL_PREFS_MASK*)(current_request->arg2)
);
break;
case RPC_SET_GLOBAL_PREFS_OVERRIDE_STRUCT:
retval = (m_Doc->rpcClient).set_global_prefs_override_struct(
retval = (m_pDoc->rpcClient).set_global_prefs_override_struct(
*(GLOBAL_PREFS*)(current_request->arg1),
*(GLOBAL_PREFS_MASK*)(current_request->arg2)
);
break;
case RPC_SET_DEBTS:
retval = (m_Doc->rpcClient).set_debts(*(std::vector<PROJECT>*)(current_request->arg1));
retval = (m_pDoc->rpcClient).set_debts(*(std::vector<PROJECT>*)(current_request->arg1));
break;
default:
break;
@ -576,7 +578,7 @@ int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority) {
}
void CMainDocument::OnRPCComplete(CRPCFinishedEvent&) {
void CMainDocument::OnRPCComplete() {
HandleCompletedRPC();
}
@ -591,7 +593,6 @@ void CMainDocument::HandleCompletedRPC() {
// called from RequestRPC, the CRPCFinishedEvent will still be
// on the event queue, so we get called twice. Check for this here.
if (current_rpc_request.which_rpc == 0) return; // already handled by a call from RequestRPC
// m_RPCThread->Pause();
// Find our completed request in the queue
n = RPC_requests.size();

View File

@ -23,10 +23,8 @@
#endif
class CBOINCGUIApp; // Forward declaration
class CMainDocument; // Forward declaration
enum RPC_SELECTOR {
RPC_AUTHORIZE = 1,
RPC_EXCHANGE_VERSIONS,
@ -282,7 +280,7 @@ public:
{ return RPC_Wait(RPC_SET_DEBTS, (void*)&arg1); }
private:
CMainDocument *m_Doc;
CMainDocument* m_pDoc;
};
@ -295,7 +293,7 @@ public:
private:
int ProcessRPCRequest();
CMainDocument *m_Doc;
CMainDocument* m_pDoc;
};
@ -309,25 +307,4 @@ public:
};
class CRPCFinishedEvent : public wxEvent
{
public:
CRPCFinishedEvent(wxEventType evtType)
: wxEvent(-1, evtType)
{
SetEventObject(wxTheApp);
}
virtual wxEvent *Clone() const { return new CRPCFinishedEvent(*this); }
};
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE( wxEVT_RPC_FINISHED, -1 )
END_DECLARE_EVENT_TYPES()
#define EVT_RPC_FINISHED(fn) \
DECLARE_EVENT_TABLE_ENTRY(wxEVT_RPC_FINISHED, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
#endif // _ASYNCRPC_H_

View File

@ -43,6 +43,7 @@ DEFINE_EVENT_TYPE(wxEVT_FRAME_INITIALIZED)
DEFINE_EVENT_TYPE(wxEVT_FRAME_REFRESHVIEW)
DEFINE_EVENT_TYPE(wxEVT_FRAME_UPDATESTATUS)
DEFINE_EVENT_TYPE(wxEVT_FRAME_RELOADSKIN)
DEFINE_EVENT_TYPE(wxEVT_FRAME_RPCFINISHED)
IMPLEMENT_DYNAMIC_CLASS(CBOINCBaseFrame, wxFrame)
@ -54,6 +55,7 @@ BEGIN_EVENT_TABLE (CBOINCBaseFrame, wxFrame)
EVT_FRAME_INITIALIZED(CBOINCBaseFrame::OnInitialized)
EVT_FRAME_ALERT(CBOINCBaseFrame::OnAlert)
EVT_FRAME_REFRESH(CBOINCBaseFrame::OnRefreshView)
EVT_FRAME_RPCFINISHED(CBOINCBaseFrame::OnRPCFinished)
EVT_CLOSE(CBOINCBaseFrame::OnClose)
EVT_MENU(ID_FILECLOSEWINDOW, CBOINCBaseFrame::OnCloseWindow)
END_EVENT_TABLE ()
@ -163,6 +165,16 @@ void CBOINCBaseFrame::OnPeriodicRPC(wxTimerEvent& WXUNUSED(event)) {
}
void CBOINCBaseFrame::OnRPCFinished( CFrameEvent& /* event */ ) {
CMainDocument* pDoc = wxGetApp().GetDocument();
wxASSERT(pDoc);
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
pDoc->OnRPCComplete();
}
void CBOINCBaseFrame::OnDocumentPoll(wxTimerEvent& WXUNUSED(event)) {
static bool bAlreadyRunOnce = false;
CMainDocument* pDoc = wxGetApp().GetDocument();
@ -355,6 +367,11 @@ void CBOINCBaseFrame::OnExit(wxCommandEvent& WXUNUSED(event)) {
}
int CBOINCBaseFrame::GetCurrentViewPage() {
return _GetCurrentViewPage();
}
void CBOINCBaseFrame::FireInitialize() {
CFrameEvent event(wxEVT_FRAME_INITIALIZED, this);
AddPendingEvent(event);
@ -369,9 +386,6 @@ void CBOINCBaseFrame::FireRefreshView() {
pDoc->RefreshRPCs();
pDoc->RunPeriodicRPCs();
// CFrameEvent event(wxEVT_FRAME_REFRESHVIEW, this);
// AddPendingEvent(event);
}
@ -387,6 +401,12 @@ void CBOINCBaseFrame::FireReloadSkin() {
}
void CBOINCBaseFrame::FireRPCFinished() {
CFrameEvent event(wxEVT_FRAME_RPCFINISHED, this);
AddPendingEvent(event);
}
void CBOINCBaseFrame::ShowConnectionBadPasswordAlert( bool bUsedDefaultPassword, int m_iReadGUIRPCAuthFailure ) {
CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
wxString strDialogTitle = wxEmptyString;
@ -755,25 +775,26 @@ bool CBOINCBaseFrame::RestoreState() {
return true;
}
#ifdef __WXMAC__
bool CBOINCBaseFrame::Show(bool show) {
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
if (show) {
SetFrontProcess(&psn); // Shows process if hidden
/*
bool CBOINCBaseFrame::Show(bool bShow) {
if (bShow) {
wxGetApp().ShowApplication(true);
} else {
// GetWindowDimensions();
if (wxGetApp().GetCurrentGUISelection() == m_iWindowType)
if (IsProcessVisible(&psn))
ShowHideProcess(&psn, false);
if ( this == wxGetApp().GetFrame() ) {
if (wxGetApp().IsApplicationVisible()) {
wxGetApp().ShowApplication(false);
}
}
}
return wxFrame::Show(show);
}
*/
#endif // __WXMAC__
int CBOINCBaseFrame::_GetCurrentViewPage() {
wxASSERT(false);
return 0;
}
void CFrameAlertEvent::ProcessResponse(const int response) const {

View File

@ -51,6 +51,8 @@ public:
~CBOINCBaseFrame();
void OnPeriodicRPC( wxTimerEvent& event );
void OnRPCFinished( CFrameEvent& event );
void OnDocumentPoll( wxTimerEvent& event );
void OnAlertPoll( wxTimerEvent& event );
virtual void OnRefreshView( CFrameEvent& event );
@ -61,7 +63,9 @@ public:
virtual void OnClose( wxCloseEvent& event );
virtual void OnCloseWindow( wxCommandEvent& event );
virtual void OnExit( wxCommandEvent& event );
int GetCurrentViewPage();
int GetReminderFrequency() { return m_iReminderFrequency; }
wxString GetDialupConnectionName() { return m_strNetworkDialupConnectionName; }
@ -69,6 +73,7 @@ public:
void FireRefreshView();
void FireConnect();
void FireReloadSkin();
void FireRPCFinished();
void ShowConnectionBadPasswordAlert( bool bUsedDefaultPassword, int m_iReadGUIRPCAuthFailure );
void ShowConnectionFailedAlert();
void ShowDaemonStartFailedAlert();
@ -89,10 +94,7 @@ public:
void ExecuteBrowserLink( const wxString& strLink );
#ifdef __WXMAC__
bool Show( bool show = true );
int m_iWindowType; // BOINC_SIMPLEGUI or BOINC_ADVANCEDGUI
#endif
//bool Show( bool bShow = true );
protected:
@ -111,6 +113,8 @@ protected:
bool m_bShowConnectionFailedAlert;
virtual int _GetCurrentViewPage();
virtual bool SaveState();
virtual bool RestoreState();
@ -183,7 +187,7 @@ DECLARE_EVENT_TYPE( wxEVT_FRAME_INITIALIZED, 10004 )
DECLARE_EVENT_TYPE( wxEVT_FRAME_REFRESHVIEW, 10005 )
DECLARE_EVENT_TYPE( wxEVT_FRAME_UPDATESTATUS, 10006 )
DECLARE_EVENT_TYPE( wxEVT_FRAME_RELOADSKIN, 10007 )
DECLARE_EVENT_TYPE( wxEVT_FRAME_RPCFINISHED, 10008 )
END_DECLARE_EVENT_TYPES()
#define EVT_FRAME_ALERT(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_FRAME_ALERT, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
@ -192,7 +196,7 @@ END_DECLARE_EVENT_TYPES()
#define EVT_FRAME_REFRESH(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_FRAME_REFRESHVIEW, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
#define EVT_FRAME_UPDATESTATUS(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_FRAME_UPDATESTATUS, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
#define EVT_FRAME_RELOADSKIN(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_FRAME_RELOADSKIN, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
#define EVT_FRAME_RPCFINISHED(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_FRAME_RPCFINISHED, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
#endif

View File

@ -603,8 +603,7 @@ void CBOINCBaseView::ClearSavedSelections() {
// Save the key values of the currently selected rows for later restore
void CBOINCBaseView::SaveSelections() {
int currentTabView = wxGetApp().GetCurrentViewPage();
if (! (currentTabView & (VW_PROJ | VW_TASK | VW_XFER))) {
if (!_ManageSelections()) {
return;
}
@ -630,8 +629,7 @@ void CBOINCBaseView::SaveSelections() {
// previous selection and makes any adjustments to ensure that
// the rows containing the originally selected data are selected.
void CBOINCBaseView::RestoreSelections() {
int currentTabView = wxGetApp().GetCurrentViewPage();
if (! (currentTabView & (VW_PROJ | VW_TASK | VW_XFER))) {
if (!_ManageSelections()) {
return;
}
@ -777,6 +775,16 @@ void CBOINCBaseView::UpdateWebsiteSelection(long lControlGroup, PROJECT* project
}
bool CBOINCBaseView::_ManageSelections() {
return ManageSelections();
}
bool CBOINCBaseView::ManageSelections() {
return false;
}
bool CBOINCBaseView::_EnsureLastItemVisible() {
return EnsureLastItemVisible();
}

View File

@ -165,6 +165,10 @@ protected:
virtual void UpdateWebsiteSelection(long lControlGroup, PROJECT* project);
bool _ManageSelections();
virtual bool ManageSelections();
bool _EnsureLastItemVisible();
virtual bool EnsureLastItemVisible();

View File

@ -155,7 +155,7 @@ bool CBOINCClientManager::StartupBOINCCore() {
LPTSTR szDataDirectory = NULL;
if (IsBOINCConfiguredAsDaemon()) {
return (StartBOINCService());
return StartBOINCService() == TRUE;
}
// Append boinc.exe to the end of the strExecute string and get ready to rock

File diff suppressed because it is too large Load Diff

View File

@ -32,20 +32,12 @@
#include "mac/MacSysMenu.h" // Must be included before MainDocument.h
#endif
///
/// Which view is on display
///
#define BOINC_ADVANCEDGUI 1
#define BOINC_SIMPLEGUI 2
// Bit values for CBOINCGUIApp::GetCurrentView() and
// CMainDocument::RunPeriodicRPCs()
#define VW_PROJ 1
#define VW_TASK 2
#define VW_XFER 4
#define VW_MSGS 8
#define VW_STAT 16
#define VW_DISK 32
#define VW_SGUI 1024
#define VW_SMSG 2048
class wxLogBOINC;
class CBOINCBaseFrame;
@ -56,6 +48,7 @@ class CRPCFinishedEvent;
class CBOINCGUIApp : public wxApp {
DECLARE_DYNAMIC_CLASS(CBOINCGUIApp)
protected:
@ -65,13 +58,11 @@ protected:
bool OnCmdLineParsed(wxCmdLineParser &parser);
void DetectDisplayInfo();
void DetectRootDirectory();
void DetectDataDirectory();
void InitSupportedLanguages();
#ifdef __WXMAC__
static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon );
#endif
int ClientLibraryStartup();
int IdleTrackerAttach();
int IdleTrackerDetach();
@ -101,6 +92,10 @@ protected:
#ifdef __WXMSW__
HINSTANCE m_hClientLibraryDll;
#endif
#ifdef __WXMAC__
ProcessSerialNumber m_psnCurrentProcess;
#endif
// The last value defined in the wxLanguage enum is wxLANGUAGE_USER_DEFINED.
// defined in: wx/intl.h
@ -116,14 +111,9 @@ public:
bool OnInit();
int UpdateSystemIdleDetection();
int StartBOINCScreensaverTest();
wxLocale* GetLocale() { return m_pLocale; }
CSkinManager* GetSkinManager() { return m_pSkinManager; }
CBOINCBaseFrame* GetFrame() { return m_pFrame; }
void FrameClosed() { m_pFrame = NULL; }
CMainDocument* GetDocument() { return m_pDocument; }
wxString GetArguments() { return m_strBOINCArguments; }
wxString GetRootDirectory() { return m_strBOINCMGRRootDirectory; }
@ -133,33 +123,41 @@ public:
#endif
#ifdef __WXMAC__
CMacSystemMenu* GetMacSystemMenu() { return m_pMacSystemMenu; }
int GetCurrentGUISelection() { return m_iGUISelected; }
#endif
wxArrayString& GetSupportedLanguages() { return m_astrLanguages; }
int GetDisplayExitWarning() { return m_iDisplayExitWarning; }
int GetDisplayExitWarning() { return m_iDisplayExitWarning; }
void SetDisplayExitWarning(int display) { m_iDisplayExitWarning = display; }
void FireReloadSkin();
void FrameClosed() { m_pFrame = NULL; }
int StartBOINCScreensaverTest();
bool SetActiveGUI(int iGUISelection, bool bShowWindow = true);
int GetCurrentViewPage();
virtual void OnRPCFinished( CRPCFinishedEvent& event );
void OnRPCFinished( CRPCFinishedEvent& event );
int ConfirmExit();
int SafeMessageBox(const wxString& message,
const wxString& caption = wxMessageBoxCaptionStr,
long style = wxOK | wxCENTRE,
wxWindow *parent = NULL,
int x = wxDefaultCoord, int y = wxDefaultCoord);
int SafeMessageBox(
const wxString& message,
const wxString& caption = wxMessageBoxCaptionStr,
long style = wxOK | wxCENTRE,
wxWindow *parent = NULL,
int x = wxDefaultCoord,
int y = wxDefaultCoord
);
bool IsApplicationVisible();
void ShowApplication(bool bShow);
bool IsModalDialogDisplayed();
int FilterEvent(wxEvent &event);
DECLARE_EVENT_TABLE()
int UpdateSystemIdleDetection();
};

View File

@ -231,24 +231,19 @@ void CTaskBarIcon::OnSuspendResume(wxCommandEvent& WXUNUSED(event)) {
void CTaskBarIcon::OnAbout(wxCommandEvent& WXUNUSED(event)) {
#ifdef __WXMAC__
ProcessSerialNumber psn;
bool bWasVisible;
GetCurrentProcess(&psn);
bool wasVisible = IsProcessVisible(&psn);
SetFrontProcess(&psn); // Shows process if hidden
#endif
bWasVisible = wxGetApp().IsApplicationVisible();
wxGetApp().ShowApplication(true);
ResetTaskBar();
CDlgAbout dlg(NULL);
dlg.ShowModal();
#ifdef __WXMAC__
if (!wasVisible) {
ShowHideProcess(&psn, false);
if (!bWasVisible) {
wxGetApp().ShowApplication(false);
}
#endif
}

View File

@ -28,8 +28,10 @@
#endif
#include "BOINCGUIApp.h"
#include "BOINCBaseFrame.h"
#include "MainDocument.h"
#include "BOINCBaseFrame.h"
#include "AdvancedFrame.h"
#include "sg_BoincSimpleGUI.h"
#include "BOINCClientManager.h"
#include "BOINCTaskBar.h"
#include "Events.h"
@ -769,6 +771,7 @@ void CMainDocument::RunPeriodicRPCs() {
CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
if (!pFrame) return;
wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
if (!IsConnected()) {
@ -782,10 +785,11 @@ void CMainDocument::RunPeriodicRPCs() {
pTaskbar->AddPendingEvent(event);
}
#endif
return;
}
int currentTabView = wxGetApp().GetCurrentViewPage();
int currentTabView = pFrame->GetCurrentViewPage();
// Several functions (such as Abort, Reset, Detach) display an
// "Are you sure?" dialog before passing a pointer to a result
@ -828,7 +832,7 @@ void CMainDocument::RunPeriodicRPCs() {
request.arg2 = &messages;
// request.arg2 = &async_messages_buf;
// request.exchangeBuf = &messages;
request.rpcType = (currentTabView & VW_MSGS) ?
request.rpcType = (currentTabView & VW_MSGS) ?
RPC_TYPE_ASYNC_WITH_REFRESH_AFTER : RPC_TYPE_ASYNC_WITH_UPDATE_MESSAGE_LIST_AFTER;
request.completionTime = NULL;
request.resultPtr = &m_iGet_messages_rpc_result;

View File

@ -176,7 +176,7 @@ public:
//
public:
int RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority = false);
void OnRPCComplete(CRPCFinishedEvent& event);
void OnRPCComplete();
void HandleCompletedRPC();
ASYNC_RPC_REQUEST* GetCurrentRPCRequest() { return &current_rpc_request; }
bool WaitingForRPC() { return m_bWaitingForRPC; }

View File

@ -643,6 +643,10 @@ wxInt32 CViewProjects::RemoveCacheElement() {
}
bool CViewProjects::ManageSelections() {
return true;
}
void CViewProjects::UpdateSelection() {
CTaskItemGroup* pGroup = NULL;
PROJECT* project = NULL;

View File

@ -84,6 +84,8 @@ protected:
virtual wxInt32 RemoveCacheElement();
virtual bool SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex);
virtual bool ManageSelections();
virtual void UpdateSelection();
void GetDocProjectName(wxInt32 item, wxString& strBuffer) const;

View File

@ -433,6 +433,11 @@ wxInt32 CViewTransfers::RemoveCacheElement() {
}
bool CViewTransfers::ManageSelections() {
return true;
}
void CViewTransfers::UpdateSelection() {
CTaskItemGroup* pGroup = m_TaskGroups[0];

View File

@ -79,6 +79,8 @@ protected:
virtual wxInt32 RemoveCacheElement();
virtual bool SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex);
virtual bool ManageSelections();
virtual void UpdateSelection();
void GetDocProjectName(wxInt32 item, wxString& strBuffer) const;

View File

@ -580,6 +580,11 @@ wxInt32 CViewWork::RemoveCacheElement() {
}
bool CViewWork::ManageSelections() {
return true;
}
void CViewWork::UpdateSelection() {
CTaskItemGroup* pGroup = NULL;
RESULT* result = NULL;

View File

@ -85,6 +85,9 @@ protected:
virtual wxInt32 GetCacheCount();
virtual wxInt32 RemoveCacheElement();
virtual bool SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex);
virtual bool ManageSelections();
virtual void UpdateSelection();
void GetDocProjectName(wxInt32 item, wxString& strBuffer) const;

View File

@ -521,7 +521,7 @@ void CWelcomePage::OnShow( wxShowEvent& event ) {
* event handler for ID_WELCOMEPAGE
*/
void CWelcomePage::OpenWCG( wxCommandEvent& event ) {
void CWelcomePage::OpenWCG( wxCommandEvent& /* event */ ) {
wxLogTrace(wxT("Function Start/End"), wxT("CWelcomePage::OpenWCG - Function Begin"));
wxString wcgUrl("http://www.worldcommunitygrid.org/ms/viewMyProjects.do", wxConvUTF8);
wxHyperLink::ExecuteLink(wcgUrl);

View File

@ -298,6 +298,16 @@ bool CSimpleFrame::SaveState() {
}
int CSimpleFrame::_GetCurrentViewPage() {
if (isMessagesDlgOpen()) {
return VW_SGUI | VW_SMSG;
} else {
return VW_SGUI;
}
return 0; // Should never happen.
}
void CSimpleFrame::OnHelp(wxHelpEvent& event) {
wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelp - Function Begin"));

View File

@ -23,6 +23,14 @@
#pragma interface "sg_BoincSimpleGUI.cpp"
#endif
///
/// Bitmask values for CMainDocument::RunPeriodicRPCs()
///
#define VW_SGUI 1024
#define VW_SMSG 2048
class CViewTabPage;
class StatImageLoader;
class ImageLoader;
@ -113,21 +121,22 @@ public:
void SetMsgsDlgOpen(CDlgMessages* newDlgPtr) { dlgMsgsPtr = newDlgPtr; }
bool isMessagesDlgOpen() { return (dlgMsgsPtr != NULL); }
private:
bool SaveState();
bool RestoreState();
CDlgMessages* dlgMsgsPtr;
protected:
virtual int _GetCurrentViewPage();
wxAcceleratorEntry m_Shortcuts[1];
wxAcceleratorTable* m_pAccelTable;
CSimplePanel* m_pBackgroundPanel;
#ifdef __WXMAC__
wxMenuBar* m_pMenubar;
#endif
wxAcceleratorEntry m_Shortcuts[1];
wxAcceleratorTable* m_pAccelTable;
CSimplePanel* m_pBackgroundPanel;
private:
bool SaveState();
bool RestoreState();
CDlgMessages* dlgMsgsPtr;
DECLARE_EVENT_TABLE()
};

Binary file not shown.

Binary file not shown.

View File

@ -497,6 +497,8 @@
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="boinc_win.h"
PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
ExpandAttributedSource="true"
AssemblerOutput="2"
AssemblerListingLocation=""
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\vc80.pdb"