mirror of https://github.com/BOINC/boinc.git
svn path=/trunk/boinc/; revision=20269
This commit is contained in:
parent
904137dfd6
commit
42683a8a31
|
@ -667,3 +667,27 @@ David 25 Jan 2010
|
||||||
|
|
||||||
client/
|
client/
|
||||||
app_start.cpp
|
app_start.cpp
|
||||||
|
|
||||||
|
David 26 Jan 2010
|
||||||
|
- client/manager: eliminate duplicate notices.
|
||||||
|
When appending a new notice, we check whether one with
|
||||||
|
the same title and description is present already.
|
||||||
|
If so we remove one or the other, depending on the situation.
|
||||||
|
|
||||||
|
This introduces the possibility of "holes" in the seqno space.
|
||||||
|
In order that the manager learns of these deletions,
|
||||||
|
we use the following mechanism:
|
||||||
|
whenever a notice is removed (because it's a dup or too old)
|
||||||
|
a flag is set in each GUI_RPC_CONN.
|
||||||
|
On the next get_notice() RPC, the client returns the entire
|
||||||
|
list of notices, preceded by a dummy notice with seqno=-1;
|
||||||
|
this tells the RPC stub function to replace the current list
|
||||||
|
rather than appending to it.
|
||||||
|
|
||||||
|
client/
|
||||||
|
client_msgs.cpp
|
||||||
|
cs_notice.cpp,h
|
||||||
|
gui_rpc_server.h
|
||||||
|
gui_rpc_server_ops.cpp
|
||||||
|
samples/multi_thread/
|
||||||
|
multi_thread.cpp
|
||||||
|
|
|
@ -88,7 +88,7 @@ void MESSAGE_DESCS::insert(PROJECT* p, int priority, int now, char* message) {
|
||||||
}
|
}
|
||||||
n.create_time = n.arrival_time = gstate.now;
|
n.create_time = n.arrival_time = gstate.now;
|
||||||
strcpy(n.category, "client");
|
strcpy(n.category, "client");
|
||||||
notices.append(n);
|
notices.append(n, false, false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::set;
|
using std::set;
|
||||||
|
using std::deque;
|
||||||
|
|
||||||
NOTICES notices;
|
NOTICES notices;
|
||||||
RSS_FEEDS rss_feeds;
|
RSS_FEEDS rss_feeds;
|
||||||
|
@ -230,6 +231,7 @@ void NOTICES::init() {
|
||||||
if (log_flags.notice_debug) {
|
if (log_flags.notice_debug) {
|
||||||
msg_printf(0, MSG_INFO, "read %d BOINC notices", (int)notices.size());
|
msg_printf(0, MSG_INFO, "read %d BOINC notices", (int)notices.size());
|
||||||
}
|
}
|
||||||
|
write_archive(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NOTICES::init_rss() {
|
void NOTICES::init_rss() {
|
||||||
|
@ -247,35 +249,63 @@ void NOTICES::init_rss() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NOTICES::append(NOTICE& n) {
|
static inline bool equivalent(NOTICE& n1, NOTICE& n2) {
|
||||||
|
if (strcmp(n1.title, n2.title)) return false;
|
||||||
|
if (n1.description != n2.description) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're considering adding a notice n.
|
||||||
|
// See if an equivalent notice n2 is already there; if so:
|
||||||
|
// keep_old: return false
|
||||||
|
// !keep_old: delete n2
|
||||||
|
//
|
||||||
|
bool NOTICES::remove_dups(NOTICE& n, bool keep_old) {
|
||||||
|
deque<NOTICE>::iterator i = notices.begin();
|
||||||
|
bool removed_something = false;
|
||||||
|
while (i != notices.end()) {
|
||||||
|
NOTICE& n2 = *i;
|
||||||
|
if (equivalent(n, n2) || (n2.arrival_time < gstate.now - 30*86400)) {
|
||||||
|
if (keep_old) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i = notices.erase(i);
|
||||||
|
removed_something = true;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed_something) {
|
||||||
|
gstate.gui_rpcs.set_notice_refresh();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NOTICES::append(NOTICE& n, bool keep_old, bool archive) {
|
||||||
if (notices.empty()) {
|
if (notices.empty()) {
|
||||||
n.seqno = 1;
|
n.seqno = 1;
|
||||||
} else {
|
} else {
|
||||||
|
if (!remove_dups(n, keep_old)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
n.seqno = notices.front().seqno + 1;
|
n.seqno = notices.front().seqno + 1;
|
||||||
}
|
}
|
||||||
notices.push_front(n);
|
|
||||||
prune();
|
|
||||||
if (!strlen(n.feed_url)) {
|
|
||||||
write_archive(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NOTICES::append_unique(NOTICE& n) {
|
|
||||||
for (unsigned int i=0; i<notices.size(); i++) {
|
|
||||||
NOTICE& n2 = notices[i];
|
|
||||||
if (!strcmp(n.guid, n2.guid)) return false;
|
|
||||||
}
|
|
||||||
if (log_flags.notice_debug) {
|
if (log_flags.notice_debug) {
|
||||||
msg_printf(0, MSG_INFO,
|
msg_printf(0, MSG_INFO,
|
||||||
"[notice_debug] appending notice: %s",
|
"[notice_debug] appending notice: %s",
|
||||||
n.title
|
n.title
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
append(n);
|
notices.push_front(n);
|
||||||
|
if (archive && !strlen(n.feed_url)) {
|
||||||
|
write_archive(NULL);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read and parse the contents of an archive file;
|
|
||||||
|
// read and parse the contents of an archive file.
|
||||||
|
// If feed_url is empty it's a system msg, else a feed msg.
|
||||||
// insert items in NOTICES
|
// insert items in NOTICES
|
||||||
//
|
//
|
||||||
int NOTICES::read_archive_file(char* path, char* feed_url) {
|
int NOTICES::read_archive_file(char* path, char* feed_url) {
|
||||||
|
@ -313,7 +343,7 @@ int NOTICES::read_archive_file(char* path, char* feed_url) {
|
||||||
if (feed_url) {
|
if (feed_url) {
|
||||||
strcpy(n.feed_url, feed_url);
|
strcpy(n.feed_url, feed_url);
|
||||||
}
|
}
|
||||||
notices.push_front(n);
|
append(n, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,17 +354,6 @@ int NOTICES::read_archive_file(char* path, char* feed_url) {
|
||||||
return ERR_XML_PARSE;
|
return ERR_XML_PARSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get rid of old notices
|
|
||||||
//
|
|
||||||
void NOTICES::prune() {
|
|
||||||
for (;;) {
|
|
||||||
if (!notices.size()) break;
|
|
||||||
NOTICE& n = notices.back();
|
|
||||||
if (n.arrival_time > gstate.now - 30*86400) break;
|
|
||||||
notices.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write archive file for the given RSS feed
|
// write archive file for the given RSS feed
|
||||||
// (or, if NULL, non-RSS notices)
|
// (or, if NULL, non-RSS notices)
|
||||||
//
|
//
|
||||||
|
@ -368,12 +387,19 @@ void NOTICES::write_archive(RSS_FEED* rfp) {
|
||||||
// write notices newer than seqno as XML (for GUI RPC).
|
// write notices newer than seqno as XML (for GUI RPC).
|
||||||
// Write them in order of increasing seqno
|
// Write them in order of increasing seqno
|
||||||
//
|
//
|
||||||
void NOTICES::write(int seqno, MIOFILE& fout, bool public_only) {
|
void NOTICES::write(int seqno, MIOFILE& fout, bool public_only, bool notice_refresh) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
fout.printf("<notices>\n");
|
fout.printf("<notices>\n");
|
||||||
for (i=0; i<notices.size(); i++) {
|
if (notice_refresh) {
|
||||||
NOTICE& n = notices[i];
|
NOTICE n;
|
||||||
if (n.seqno <= seqno) break;
|
n.seqno = -1;
|
||||||
|
seqno = -1;
|
||||||
|
i = notices.size();
|
||||||
|
} else {
|
||||||
|
for (i=0; i<notices.size(); i++) {
|
||||||
|
NOTICE& n = notices[i];
|
||||||
|
if (n.seqno <= seqno) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (; i>0; i--) {
|
for (; i>0; i--) {
|
||||||
NOTICE& n = notices[i-1];
|
NOTICE& n = notices[i-1];
|
||||||
|
@ -485,7 +511,7 @@ int RSS_FEED::parse_items(XML_PARSER& xp, int& nitems) {
|
||||||
} else {
|
} else {
|
||||||
n.arrival_time = gstate.now;
|
n.arrival_time = gstate.now;
|
||||||
strcpy(n.feed_url, url);
|
strcpy(n.feed_url, url);
|
||||||
if (notices.append_unique(n)) {
|
if (notices.append(n, true, false)) {
|
||||||
nitems++;
|
nitems++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,14 +67,13 @@
|
||||||
|
|
||||||
struct NOTICES {
|
struct NOTICES {
|
||||||
std::deque<NOTICE> notices;
|
std::deque<NOTICE> notices;
|
||||||
void write(int seqno, MIOFILE&, bool public_only);
|
void write(int seqno, MIOFILE&, bool public_only, bool notice_refresh);
|
||||||
void append(NOTICE&);
|
bool append(NOTICE&, bool keep_old, bool archive);
|
||||||
bool append_unique(NOTICE&);
|
|
||||||
void init();
|
void init();
|
||||||
void init_rss();
|
void init_rss();
|
||||||
int read_archive_file(char* file, char* feed_url);
|
int read_archive_file(char* file, char* feed_url);
|
||||||
void write_archive(struct RSS_FEED*);
|
void write_archive(struct RSS_FEED*);
|
||||||
void prune();
|
bool remove_dups(NOTICE&, bool keep_old);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NOTICES notices;
|
extern NOTICES notices;
|
||||||
|
|
|
@ -79,6 +79,7 @@ GUI_RPC_CONN::GUI_RPC_CONN(int s):
|
||||||
got_auth1 = false;
|
got_auth1 = false;
|
||||||
got_auth2 = false;
|
got_auth2 = false;
|
||||||
sent_unauthorized = false;
|
sent_unauthorized = false;
|
||||||
|
notice_refresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI_RPC_CONN::~GUI_RPC_CONN() {
|
GUI_RPC_CONN::~GUI_RPC_CONN() {
|
||||||
|
|
|
@ -55,6 +55,9 @@ public:
|
||||||
GET_PROJECT_CONFIG_OP get_project_config_op;
|
GET_PROJECT_CONFIG_OP get_project_config_op;
|
||||||
LOOKUP_ACCOUNT_OP lookup_account_op;
|
LOOKUP_ACCOUNT_OP lookup_account_op;
|
||||||
CREATE_ACCOUNT_OP create_account_op;
|
CREATE_ACCOUNT_OP create_account_op;
|
||||||
|
bool notice_refresh;
|
||||||
|
// next time we get a get_notices RPC,
|
||||||
|
// send a -1 seqno, then the whole list
|
||||||
|
|
||||||
GUI_RPC_CONN(int);
|
GUI_RPC_CONN(int);
|
||||||
~GUI_RPC_CONN();
|
~GUI_RPC_CONN();
|
||||||
|
@ -96,4 +99,9 @@ public:
|
||||||
void send_quits();
|
void send_quits();
|
||||||
bool quits_sent();
|
bool quits_sent();
|
||||||
bool poll();
|
bool poll();
|
||||||
|
void set_notice_refresh() {
|
||||||
|
for (unsigned int i=0; i<gui_rpcs.size(); i++) {
|
||||||
|
gui_rpcs[i]->notice_refresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1055,16 +1055,16 @@ static void handle_set_cc_config(char* buf, MIOFILE& fout) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_get_notices(char* buf, MIOFILE& fout) {
|
static void handle_get_notices(char* buf, MIOFILE& fout, bool notice_refresh) {
|
||||||
int seqno = 0;
|
int seqno = 0;
|
||||||
parse_int(buf, "<seqno>", seqno);
|
parse_int(buf, "<seqno>", seqno);
|
||||||
notices.write(seqno, fout, false);
|
notices.write(seqno, fout, false, notice_refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_get_notices_public(char* buf, MIOFILE& fout) {
|
static void handle_get_notices_public(char* buf, MIOFILE& fout, bool notice_refresh) {
|
||||||
int seqno = 0;
|
int seqno = 0;
|
||||||
parse_int(buf, "<seqno>", seqno);
|
parse_int(buf, "<seqno>", seqno);
|
||||||
notices.write(seqno, fout, true);
|
notices.write(seqno, fout, true, notice_refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some of the RPCs have empty-element request messages.
|
// Some of the RPCs have empty-element request messages.
|
||||||
|
@ -1166,7 +1166,8 @@ int GUI_RPC_CONN::handle_rpc() {
|
||||||
} else if (match_req(request_msg, "get_all_projects_list")) {
|
} else if (match_req(request_msg, "get_all_projects_list")) {
|
||||||
read_all_projects_list_file(mf);
|
read_all_projects_list_file(mf);
|
||||||
} else if (match_req(request_msg, "get_notices_public")) {
|
} else if (match_req(request_msg, "get_notices_public")) {
|
||||||
handle_get_notices_public(request_msg, mf);
|
handle_get_notices_public(request_msg, mf, notice_refresh);
|
||||||
|
notice_refresh = false;
|
||||||
|
|
||||||
// Operations that require authentication start here
|
// Operations that require authentication start here
|
||||||
|
|
||||||
|
@ -1247,7 +1248,8 @@ int GUI_RPC_CONN::handle_rpc() {
|
||||||
} else if (match_req(request_msg, "set_debts")) {
|
} else if (match_req(request_msg, "set_debts")) {
|
||||||
handle_set_debts(request_msg, mf);
|
handle_set_debts(request_msg, mf);
|
||||||
} else if (match_req(request_msg, "get_notices")) {
|
} else if (match_req(request_msg, "get_notices")) {
|
||||||
handle_get_notices(request_msg, mf);
|
handle_get_notices(request_msg, mf, notice_refresh);
|
||||||
|
notice_refresh = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// RPCs after this point require authentication,
|
// RPCs after this point require authentication,
|
||||||
|
|
|
@ -16,7 +16,11 @@
|
||||||
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Example multi-thread BOINC application.
|
// Example multi-thread BOINC application.
|
||||||
// It does 64 "units" of computation, where each units is about 1 GFLOP.
|
// This app defines its own classes (THREAD, THREAD_SET) for managing threads.
|
||||||
|
// You can also use libraries such as OpenMP.
|
||||||
|
// Just make sure you call boinc_init_parallel().
|
||||||
|
//
|
||||||
|
// This app does 64 "units" of computation, where each units is about 1 GFLOP.
|
||||||
// It divides this among N "worker" threads.
|
// It divides this among N "worker" threads.
|
||||||
// N is passed in the command line, and defaults to 1.
|
// N is passed in the command line, and defaults to 1.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue