-
Notifications
You must be signed in to change notification settings - Fork 3
/
gtagsmixer.h
159 lines (141 loc) · 5.83 KB
/
gtagsmixer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2007 Google Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// Author: [email protected] (Stephen Chen)
//
// gtagsmixer provides a network interface on user's local machine through which
// a client can talk to GTags servers on mulitple data centers using stubby/RPC.
//
// When an RPC call finishes, the callback will attempt to report the result to
// a ResultHolder object. There is a common ResultHolder object per Datasource
// per request. We are only interested in the fastest result from each
// DataSource, so only the first attempt to set the result on each ResultHolder
// object has any effects. All the results from different ResultHolders are then
// collected in a ResultMixer. ResultMixer is responsibly for mixing and ranking
// results from different DataSources and send them back to the client.
//
// See: gtagsmixermain.cc for details on gtagsmixer's initialization.
// See: mixerconnection.[h|cc] for details on network communication
// with the client.
#ifndef TOOLS_TAGS_GTAGSMIXER_H__
#define TOOLS_TAGS_GTAGSMIXER_H__
#include <list>
#include "callback.h"
#include "mutex.h"
#include "sexpression.h"
using gtags::Mutex;
// We mix tags results from the following sources. The ordering here determines
// ranking.
//
// proto refers to protocol buffer gtags server which we query with every
// request regardless of the language.
//
// remote_query refers to remote gtags servers on borg cell that are identified
// by the query language and caller type.
//
// TODO(stephenchen): We want to provide a web interface to make the ordering
// configurable.
enum SourceId { LOCAL, REMOTE, NUM_SOURCES_PER_REQUEST };
// ResultMixer is responsible for ranking and mixing tags results from
// different sources.
//
// When created, TagsMixer takes the number of results that it expects to handle
// as a parameter. Tags results (or failures) are reported by tags result
// holders Once all the responses arrived, ResultMixer will unpack all the
// results and recombine them. The ranking rule is based on the ordering of the
// sources in SourceId list.
//
// After mixing is done, it invokes a specified callback and self destructs.
class ResultMixer {
protected:
typedef gtags::Callback1<void, const string&> DoneCallback;
public:
ResultMixer(int num_sources, DoneCallback* callback)
: num_sources_(num_sources), waiting_for_(num_sources),
callback_(callback) {
results_ = new string[num_sources];
failures_ = new string[num_sources];
}
~ResultMixer() {
delete [] results_;
delete [] failures_;
}
// Report result from one source to the mixer. If the caller is the last
// source the mixer is waiting for, tag results are mixed and callback is
// invoked.
virtual void set_result(const string& result, SourceId id);
// Report a failure from one source to the mixer. If the caller is the last
// source the mixer is waiting for, tag results are mixed and callback is
// invoked.
virtual void set_failure(const string& reason, SourceId id);
protected:
// Mix and rank tag results from different sources.
// Result is appended to output.
virtual void MixResult(string* output);
// Takes a number of SExpression lists and merge them into one list.
// Result is appended to output.
virtual void JoinResults(const list<const SExpression*>& sexpressions,
string* oupput);
// Check if we all data from all the sources we need. If so, mix the
// result and invoke the callback.
// Note: caller is responsible for locking mu_.
virtual bool CheckIfDone();
private:
// Mutex for thread control.
Mutex mu_;
// Number of sources we are expected to mix.
int num_sources_;
// Number of outstanding sources.
int waiting_for_;
// Function to invoke once we have a merged result.
DoneCallback* callback_;
// List of results.
string* results_;
// List of failure messages.
string* failures_;
};
// Thread safe container for tag query result.
//
// ResultHolder is used in the callback function of the TagsService.GetTags
// stubby RPC call. Normally, there are multiple RPC calls happening
// concurrently in separate threads and MixerResultHolder is used to select the
// fastest result. When each RPC call finishes, the callback function will
// invoke set_tag with the result. Only the first call to set_tag triggers a
// response back to the client. Subsequent calls to set_tag have no
// effect. set_tag is guarded using a lock to ensure thread safety.
//
// ResultHolder self destructs when the total number of calls to set_result and
// set_failure reaches num_conn.
class ResultHolder {
public:
ResultHolder(SourceId id, int num_conn, ResultMixer* mixer) :
mixer_(mixer), id_(id), num_conn_(num_conn), num_waiting_(num_conn),
used_(false) {}
~ResultHolder() {}
// Report result to mixer when called for the first time. Does nothing on
// subsequent calls.
void set_result(const string& result);
// Report failure to mixer when called num_conn number of times.
void set_failure(const string& reason);
private:
ResultMixer* mixer_;
SourceId id_;
int num_conn_;
int num_waiting_;
bool used_;
Mutex mu_;
};
#endif // TOOLS_TAGS_GTAGSMIXER_H__