This commit is contained in:
Jacob Dufault 2017-03-14 01:33:39 -07:00
parent b7923b4abe
commit bea453af79
10 changed files with 371 additions and 107 deletions

View File

@ -95,6 +95,17 @@ std::unique_ptr<InMessage> ParseMessage() {
return MessageRegistry::instance()->Parse(document); return MessageRegistry::instance()->Parse(document);
} }
std::string Join(const std::vector<std::string>& elements, std::string sep) {
bool first = true;
std::string result;
for (const auto& element : elements) {
if (!first)
result += ", ";
first = false;
result += element;
}
return result;
}
@ -176,6 +187,32 @@ void Reflect(TVisitor& visitor, IpcMessage_OpenProject& value) {
struct IpcMessage_IndexTranslationUnitRequest : public BaseIpcMessage<IpcMessage_IndexTranslationUnitRequest> {
static constexpr IpcId kIpcId = IpcId::IndexTranslationUnitRequest;
std::string path;
std::vector<std::string> args;
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, IpcMessage_IndexTranslationUnitRequest& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(path);
REFLECT_MEMBER(args);
REFLECT_MEMBER_END();
}
struct IpcMessage_IndexTranslationUnitResponse : public BaseIpcMessage<IpcMessage_IndexTranslationUnitResponse> {
static constexpr IpcId kIpcId = IpcId::IndexTranslationUnitResponse;
IndexUpdate update;
explicit IpcMessage_IndexTranslationUnitResponse(IndexUpdate& update) : update(update) {}
};
template<typename TVisitor>
void Reflect(TVisitor& visitor, IpcMessage_IndexTranslationUnitResponse& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(update);
REFLECT_MEMBER_END();
}
@ -254,24 +291,84 @@ void Reflect(TVisitor& visitor, IpcMessage_WorkspaceSymbolsResponse& value) {
struct Timer {
using Clock = std::chrono::high_resolution_clock;
std::chrono::time_point<Clock> start_;
Timer() {
Reset();
}
void Reset() {
start_ = Clock::now();
}
long long ElapsedMilliseconds() {
std::chrono::time_point<Clock> end = Clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(end - start_).count();
}
};
void IndexMainLoop(IpcClient* ipc) {
void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
std::vector<std::unique_ptr<IpcMessage>> messages = ipc->TakeMessages(); std::vector<std::unique_ptr<IpcMessage>> messages = ipc->TakeMessages();
for (auto& message : messages) {
std::cerr << "Processing message " << static_cast<int>(message->ipc_id) << std::endl;
switch (message->ipc_id) {
case IpcId::Quit: {
exit(0);
break;
}
case IpcId::IndexTranslationUnitRequest: {
IpcMessage_IndexTranslationUnitRequest* msg = static_cast<IpcMessage_IndexTranslationUnitRequest*>(message.get());
std::cerr << "Parsing file " << msg->path << " with args " << Join(msg->args, ", ") << std::endl;
Timer time;
IndexedFile file = Parse(msg->path, msg->args);
std::cerr << "Parsing/indexing took " << time.ElapsedMilliseconds() << "ms" << std::endl;
time.Reset();
auto response = IpcMessage_IndexTranslationUnitResponse(IndexUpdate(file));
std::cerr << "Creating index update took " << time.ElapsedMilliseconds() << "ms" << std::endl;
time.Reset();
ipc->SendToServer(&response);
std::cerr << "Sending to server took " << time.ElapsedMilliseconds() << "ms" << std::endl;
break;
}
}
}
}
void IndexMain(int id) {
return;
IpcClient client_ipc("indexer", id);
while (true) {
IndexMainLoop(&client_ipc);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void QueryDbMainLoop(IpcServer* client, std::vector<std::unique_ptr<IpcServer>>& indexers, QueryableDatabase* db) {
std::vector<std::unique_ptr<IpcMessage>> messages = client->TakeMessages();
for (auto& message : messages) { for (auto& message : messages) {
std::cerr << "Processing message " << static_cast<int>(message->ipc_id) << std::endl; std::cerr << "Processing message " << static_cast<int>(message->ipc_id) << std::endl;
@ -283,7 +380,7 @@ void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
case IpcId::IsAlive: { case IpcId::IsAlive: {
IpcMessage_IsAlive response; IpcMessage_IsAlive response;
ipc->SendToClient(0, &response); // todo: make non-blocking client->SendToClient(&response); // todo: make non-blocking
break; break;
} }
@ -296,15 +393,29 @@ void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
for (int i = 0; i < entries.size(); ++i) { for (int i = 0; i < entries.size(); ++i) {
const CompilationEntry& entry = entries[i]; const CompilationEntry& entry = entries[i];
std::string filepath = path + "/" + entry.filename; std::string filepath = path + "/" + entry.filename;
std::cerr << "[" << i << "/" << (entries.size() - 1) << "] Parsing file " << filepath << std::endl; std::cerr << "[" << i << "/" << (entries.size() - 1) << "] Dispatching index request for file " << filepath << std::endl;
IndexedFile file = Parse(filepath, entry.args);
IndexUpdate update(file); // TODO: indexers should steal work. load balance.
db->ApplyIndexUpdate(&update); IpcMessage_IndexTranslationUnitRequest request;
request.path = filepath;
request.args = entry.args;
indexers[i % indexers.size()]->SendToClient(&request);
//IndexedFile file = Parse(filepath, entry.args);
//IndexUpdate update(file);
//db->ApplyIndexUpdate(&update);
} }
std::cerr << "Done" << std::endl; std::cerr << "Done" << std::endl;
break; break;
} }
case IpcId::IndexTranslationUnitResponse: {
IpcMessage_IndexTranslationUnitResponse* msg = static_cast<IpcMessage_IndexTranslationUnitResponse*>(message.get());
Timer time;
db->ApplyIndexUpdate(&msg->update);
std::cerr << "Applying index update took " << time.ElapsedMilliseconds() << "ms" << std::endl;
break;
}
case IpcId::DocumentSymbolsRequest: { case IpcId::DocumentSymbolsRequest: {
auto msg = static_cast<IpcMessage_DocumentSymbolsRequest*>(message.get()); auto msg = static_cast<IpcMessage_DocumentSymbolsRequest*>(message.get());
@ -376,7 +487,7 @@ void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
ipc->SendToClient(0, &response); client->SendToClient(&response);
break; break;
} }
@ -466,7 +577,7 @@ void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
} }
ipc->SendToClient(0, &response); client->SendToClient(&response);
break; break;
} }
@ -515,7 +626,7 @@ void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
// blocks. // blocks.
// //
// |ipc| is connected to a server. // |ipc| is connected to a server.
void LanguageServerStdinLoop(IpcClient* ipc) { void LanguageServerStdinLoop(IpcClient* server) {
while (true) { while (true) {
std::unique_ptr<InMessage> message = ParseMessage(); std::unique_ptr<InMessage> message = ParseMessage();
@ -533,7 +644,7 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
std::cerr << "Initialize in directory " << project_path << " with uri " << request->params.rootUri->raw_uri << std::endl; std::cerr << "Initialize in directory " << project_path << " with uri " << request->params.rootUri->raw_uri << std::endl;
IpcMessage_OpenProject open_project; IpcMessage_OpenProject open_project;
open_project.project_path = project_path; open_project.project_path = project_path;
ipc->SendToServer(&open_project); server->SendToServer(&open_project);
} }
auto response = Out_InitializeResponse(); auto response = Out_InitializeResponse();
@ -554,7 +665,7 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
ipc_request.request_id = request->id.value(); ipc_request.request_id = request->id.value();
ipc_request.document = request->params.textDocument.uri.GetPath(); ipc_request.document = request->params.textDocument.uri.GetPath();
std::cerr << "Request textDocument=" << ipc_request.document << std::endl; std::cerr << "Request textDocument=" << ipc_request.document << std::endl;
ipc->SendToServer(&ipc_request); server->SendToServer(&ipc_request);
break; break;
} }
@ -565,7 +676,7 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
ipc_request.request_id = request->id.value(); ipc_request.request_id = request->id.value();
ipc_request.query = request->params.query; ipc_request.query = request->params.query;
std::cerr << "Request query=" << ipc_request.query << std::endl; std::cerr << "Request query=" << ipc_request.query << std::endl;
ipc->SendToServer(&ipc_request); server->SendToServer(&ipc_request);
break; break;
} }
} }
@ -611,6 +722,8 @@ void LanguageServerMainLoop(IpcClient* ipc) {
} }
} }
const int kNumIndexers = 8 - 1;
void LanguageServerMain(std::string process_name) { void LanguageServerMain(std::string process_name) {
IpcClient client_ipc("languageserver", 0); IpcClient client_ipc("languageserver", 0);
@ -622,7 +735,7 @@ void LanguageServerMain(std::string process_name) {
client_ipc.SendToServer(&check_alive); client_ipc.SendToServer(&check_alive);
// TODO: Tune this value or make it configurable. // TODO: Tune this value or make it configurable.
std::this_thread::sleep_for(std::chrono::milliseconds(20)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
// Check if we got an IsAlive message back. // Check if we got an IsAlive message back.
std::vector<std::unique_ptr<IpcMessage>> messages = client_ipc.TakeMessages(); std::vector<std::unique_ptr<IpcMessage>> messages = client_ipc.TakeMessages();
@ -663,15 +776,33 @@ void LanguageServerMain(std::string process_name) {
std::thread stdio_reader(&LanguageServerStdinLoop, &client_ipc); std::thread stdio_reader(&LanguageServerStdinLoop, &client_ipc);
if (!has_server) { if (!has_server) {
std::vector<std::unique_ptr<IpcServer>> server_indexers;
IpcServer server_ipc("languageserver", 0);
QueryableDatabase db;
// No server. Run it in-process. // No server. Run it in-process.
new std::thread([&]() { new std::thread([&]() {
IpcServer server_ipc("languageserver");
QueryableDatabase db; std::cerr << "!! starting processes" << std::endl;
// Start indexer processes.
// TODO: make sure to handle this when running querydb out of process.
for (int i = 0; i < kNumIndexers; ++i) {
server_indexers.emplace_back(MakeUnique<IpcServer>("indexer", i + 1));
//new Process(process_name + " --indexer " + std::to_string(i + 1));
new std::thread([i]() {
IndexMain(i + 1);
});
}
std::cerr << "!! done processes" << std::endl;
while (true) { while (true) {
QueryDbMainLoop(&server_ipc, &db); QueryDbMainLoop(&server_ipc, server_indexers, &db);
// TODO: use a condition variable. std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::this_thread::sleep_for(std::chrono::microseconds(0));
} }
}); });
} }
@ -679,8 +810,7 @@ void LanguageServerMain(std::string process_name) {
// Run language client. // Run language client.
while (true) { while (true) {
LanguageServerMainLoop(&client_ipc); LanguageServerMainLoop(&client_ipc);
// TODO: use a condition variable. std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::this_thread::sleep_for(std::chrono::microseconds(0));
} }
} }
@ -733,7 +863,7 @@ void LanguageServerMain(std::string process_name) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
bool loop = false; bool loop = false;
while (loop) while (loop)
std::this_thread::sleep_for(std::chrono::milliseconds(16)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (argc == 1) { if (argc == 1) {
RunTests(); RunTests();
@ -775,6 +905,7 @@ int main(int argc, char** argv) {
LanguageServerMain(argv[0]); LanguageServerMain(argv[0]);
return 0; return 0;
} }
/* TODO: out of process querydb -- maybe?
else if (HasOption(options, "--querydb")) { else if (HasOption(options, "--querydb")) {
std::cerr << "Running querydb" << std::endl; std::cerr << "Running querydb" << std::endl;
QueryableDatabase db; QueryableDatabase db;
@ -782,10 +913,17 @@ int main(int argc, char** argv) {
while (true) { while (true) {
QueryDbMainLoop(&ipc, &db); QueryDbMainLoop(&ipc, &db);
// TODO: use a condition variable. // TODO: use a condition variable.
std::this_thread::sleep_for(std::chrono::milliseconds(20)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
return 0; return 0;
} }
*/
else if (HasOption(options, "--indexer")) {
int index = atoi(options["--indexer"].c_str());
if (index == 0)
std::cerr << "--indexer expects an indexer id > 0" << std::endl;
IndexMain(index);
}
else { else {
std::cerr << "Running language server" << std::endl; std::cerr << "Running language server" << std::endl;
LanguageServerMain(argv[0]); LanguageServerMain(argv[0]);

View File

@ -39,7 +39,7 @@ std::vector<CompilationEntry> LoadFromDirectoryListing(const std::string& projec
CompilationEntry entry; CompilationEntry entry;
entry.directory = "."; entry.directory = ".";
entry.filename = file; entry.filename = file;
entry.args = {}; entry.args = args;
result.push_back(entry); result.push_back(entry);
} }
} }

View File

@ -630,7 +630,7 @@ clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor, clang
VarId ref_id = db->ToVarId(ref_usr); VarId ref_id = db->ToVarId(ref_usr);
IndexedVarDef* ref_def = db->Resolve(ref_id); IndexedVarDef* ref_def = db->Resolve(ref_id);
Location loc = db->id_cache.Resolve(cursor, false /*interesting*/); Location loc = db->id_cache.Resolve(cursor, false /*interesting*/);
std::cerr << "Adding usage to id=" << ref_id.id << " usr=" << ref_usr << " at " << loc.ToString() << std::endl; //std::cerr << "Adding usage to id=" << ref_id.id << " usr=" << ref_usr << " at " << loc.ToString() << std::endl;
AddUsage(ref_def->uses, loc); AddUsage(ref_def->uses, loc);
break; break;
} }
@ -1117,25 +1117,6 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re
void emptyIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {} void emptyIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {}
void emptyIndexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {} void emptyIndexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {}
struct Timer {
using Clock = std::chrono::high_resolution_clock;
std::chrono::time_point<Clock> start_;
Timer() {
Reset();
}
void Reset() {
start_ = Clock::now();
}
void PrintElapsed() {
std::chrono::time_point<Clock> end = Clock::now();
std::cerr << "Indexing took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start_).count() << "ms" << std::endl;
}
};
IndexedFile Parse(std::string filename, std::vector<std::string> args, bool dump_ast) { IndexedFile Parse(std::string filename, std::vector<std::string> args, bool dump_ast) {
args.push_back("-std=c++11"); args.push_back("-std=c++11");
args.push_back("-fms-compatibility"); args.push_back("-fms-compatibility");
@ -1170,10 +1151,8 @@ IndexedFile Parse(std::string filename, std::vector<std::string> args, bool dump
NamespaceHelper ns; NamespaceHelper ns;
IndexParam param(&db, &ns); IndexParam param(&db, &ns);
Timer time;
clang_indexTranslationUnit(index_action, &param, callbacks, sizeof(callbacks), clang_indexTranslationUnit(index_action, &param, callbacks, sizeof(callbacks),
CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession, tu.cx_tu); CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession, tu.cx_tu);
time.PrintElapsed();
clang_IndexAction_dispose(index_action); clang_IndexAction_dispose(index_action);

View File

@ -13,6 +13,7 @@
#include "bitfield.h" #include "bitfield.h"
#include "utils.h" #include "utils.h"
#include "optional.h" #include "optional.h"
#include "serializer.h"
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <rapidjson/prettywriter.h> #include <rapidjson/prettywriter.h>
@ -297,6 +298,7 @@ struct TypeDefDefinitionData {
std::vector<FuncId> funcs; std::vector<FuncId> funcs;
std::vector<VarId> vars; std::vector<VarId> vars;
TypeDefDefinitionData() {} // For reflection.
TypeDefDefinitionData(const std::string& usr) : usr(usr) {} TypeDefDefinitionData(const std::string& usr) : usr(usr) {}
bool operator==(const TypeDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const { bool operator==(const TypeDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const {
@ -314,6 +316,21 @@ struct TypeDefDefinitionData {
bool operator!=(const TypeDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const { return !(*this == other); } bool operator!=(const TypeDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const { return !(*this == other); }
}; };
template<typename TVisitor, typename TypeId, typename FuncId, typename VarId, typename Location>
void Reflect(TVisitor& visitor, TypeDefDefinitionData<TypeId, FuncId, VarId, Location>& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(usr);
REFLECT_MEMBER(short_name);
REFLECT_MEMBER(qualified_name);
REFLECT_MEMBER(definition);
REFLECT_MEMBER(alias_of);
REFLECT_MEMBER(parents);
REFLECT_MEMBER(types);
REFLECT_MEMBER(funcs);
REFLECT_MEMBER(vars);
REFLECT_MEMBER_END();
}
struct IndexedTypeDef { struct IndexedTypeDef {
TypeDefDefinitionData<> def; TypeDefDefinitionData<> def;
@ -367,6 +384,7 @@ struct FuncDefDefinitionData {
// Functions that this function calls. // Functions that this function calls.
std::vector<FuncRef> callees; std::vector<FuncRef> callees;
FuncDefDefinitionData() {} // For reflection.
FuncDefDefinitionData(const std::string& usr) : usr(usr) { FuncDefDefinitionData(const std::string& usr) : usr(usr) {
//assert(usr.size() > 0); //assert(usr.size() > 0);
} }
@ -385,6 +403,20 @@ struct FuncDefDefinitionData {
bool operator!=(const FuncDefDefinitionData<TypeId, FuncId, VarId, FuncRef, Location>& other) const { return !(*this == other); } bool operator!=(const FuncDefDefinitionData<TypeId, FuncId, VarId, FuncRef, Location>& other) const { return !(*this == other); }
}; };
template<typename TVisitor, typename TypeId, typename FuncId, typename VarId, typename FuncRef, typename Location>
void Reflect(TVisitor& visitor, FuncDefDefinitionData<TypeId, FuncId, VarId, FuncRef, Location>& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(usr);
REFLECT_MEMBER(short_name);
REFLECT_MEMBER(qualified_name);
REFLECT_MEMBER(definition);
REFLECT_MEMBER(declaring_type);
REFLECT_MEMBER(base);
REFLECT_MEMBER(locals);
REFLECT_MEMBER(callees);
REFLECT_MEMBER_END();
}
struct IndexedFuncDef { struct IndexedFuncDef {
FuncDefDefinitionData<> def; FuncDefDefinitionData<> def;
@ -409,8 +441,7 @@ struct IndexedFuncDef {
bool is_bad_def = true; bool is_bad_def = true;
IndexedFuncDef() : def("") {} // For serialization IndexedFuncDef() {} // For reflection.
IndexedFuncDef(FuncId id, const std::string& usr) : id(id), def(usr) { IndexedFuncDef(FuncId id, const std::string& usr) : id(id), def(usr) {
//assert(usr.size() > 0); //assert(usr.size() > 0);
} }
@ -446,6 +477,7 @@ struct VarDefDefinitionData {
// Type which declares this one (ie, it is a method) // Type which declares this one (ie, it is a method)
optional<TypeId> declaring_type; optional<TypeId> declaring_type;
VarDefDefinitionData() {} // For reflection.
VarDefDefinitionData(const std::string& usr) : usr(usr) {} VarDefDefinitionData(const std::string& usr) : usr(usr) {}
bool operator==(const VarDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const { bool operator==(const VarDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const {
@ -461,6 +493,18 @@ struct VarDefDefinitionData {
bool operator!=(const VarDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const { return !(*this == other); } bool operator!=(const VarDefDefinitionData<TypeId, FuncId, VarId, Location>& other) const { return !(*this == other); }
}; };
template<typename TVisitor, typename TypeId, typename FuncId, typename VarId, typename Location>
void Reflect(TVisitor& visitor, VarDefDefinitionData<TypeId, FuncId, VarId, Location>& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(usr);
REFLECT_MEMBER(short_name);
REFLECT_MEMBER(qualified_name);
REFLECT_MEMBER(definition);
REFLECT_MEMBER(variable_type);
REFLECT_MEMBER(declaring_type);
REFLECT_MEMBER_END();
}
struct IndexedVarDef { struct IndexedVarDef {
VarDefDefinitionData<> def; VarDefDefinitionData<> def;

39
ipc.cc
View File

@ -1,5 +1,6 @@
#include "ipc.h" #include "ipc.h"
#include "serializer.h" #include "serializer.h"
#include "utils.h"
namespace { namespace {
// The absolute smallest partial payload we should send. This must be >0, ie, 1 is the // The absolute smallest partial payload we should send. This must be >0, ie, 1 is the
@ -230,6 +231,7 @@ void IpcDispatch(PlatformMutex* mutex, std::function<DispatchResult()> action) {
std::cerr << "[info]: shmem full, waiting (" << log_count++ << ")" << std::endl; // TODO: remove std::cerr << "[info]: shmem full, waiting (" << log_count++ << ")" << std::endl; // TODO: remove
} }
++log_iteration_count; ++log_iteration_count;
// TODO: See if we can figure out a way to use condition variables cross-process.
std::this_thread::sleep_for(std::chrono::microseconds(0)); std::this_thread::sleep_for(std::chrono::microseconds(0));
} }
first = false; first = false;
@ -263,6 +265,7 @@ void IpcDirectionalChannel::PushMessage(IpcMessage* message) {
int partial_message_id = 0; // TODO int partial_message_id = 0; // TODO
std::cerr << "Starting dispatch of payload with size " << payload_size << std::endl; std::cerr << "Starting dispatch of payload with size " << payload_size << std::endl;
int count = 0;
IpcDispatch(mutex.get(), [&]() { IpcDispatch(mutex.get(), [&]() {
assert(payload_size > 0); assert(payload_size > 0);
@ -280,7 +283,11 @@ void IpcDirectionalChannel::PushMessage(IpcMessage* message) {
shared_buffer->free_message()->Setup(message->ipc_id, partial_message_id, true /*has_more_chunks*/, sent_payload_size, payload); shared_buffer->free_message()->Setup(message->ipc_id, partial_message_id, true /*has_more_chunks*/, sent_payload_size, payload);
shared_buffer->metadata()->bytes_used += sizeof(JsonMessage) + sent_payload_size; shared_buffer->metadata()->bytes_used += sizeof(JsonMessage) + sent_payload_size;
shared_buffer->free_message()->ipc_id = IpcId::Invalid; shared_buffer->free_message()->ipc_id = IpcId::Invalid;
std::cerr << "Sending partial message with payload_size=" << sent_payload_size << std::endl;
if (count++ > 50) {
std::cerr << "x50 Sending partial message with payload_size=" << sent_payload_size << std::endl;
count = 0;
}
// Prepare for next time. // Prepare for next time.
payload_size -= sent_payload_size; payload_size -= sent_payload_size;
@ -293,7 +300,7 @@ void IpcDirectionalChannel::PushMessage(IpcMessage* message) {
shared_buffer->free_message()->Setup(message->ipc_id, partial_message_id, false /*has_more_chunks*/, payload_size, payload); shared_buffer->free_message()->Setup(message->ipc_id, partial_message_id, false /*has_more_chunks*/, payload_size, payload);
shared_buffer->metadata()->bytes_used += sizeof(JsonMessage) + payload_size; shared_buffer->metadata()->bytes_used += sizeof(JsonMessage) + payload_size;
shared_buffer->free_message()->ipc_id = IpcId::Invalid; shared_buffer->free_message()->ipc_id = IpcId::Invalid;
std::cerr << "Sending full message with payload_size=" << payload_size << std::endl; //std::cerr << "Sending full message with payload_size=" << payload_size << std::endl;
return DispatchResult::Break; return DispatchResult::Break;
} }
@ -312,24 +319,23 @@ void AddIpcMessageFromJsonMessage(std::vector<std::unique_ptr<IpcMessage>>& resu
} }
std::vector<std::unique_ptr<IpcMessage>> IpcDirectionalChannel::TakeMessages() { std::vector<std::unique_ptr<IpcMessage>> IpcDirectionalChannel::TakeMessages() {
size_t remaining_bytes = 0; std::vector<std::unique_ptr<IpcMessage>> result;
do {
// Move data from shared memory into a local buffer. Do this // Move data from shared memory into a local buffer. Do this
// before parsing the blocks so that other processes can begin // before parsing the blocks so that other processes can begin
// posting data as soon as possible. // posting data as soon as possible.
{ {
std::unique_ptr<PlatformScopedMutexLock> lock = CreatePlatformScopedMutexLock(mutex.get()); std::unique_ptr<PlatformScopedMutexLock> lock = CreatePlatformScopedMutexLock(mutex.get());
assert(shared_buffer->metadata()->bytes_used <= shmem_size); assert(shared_buffer->metadata()->bytes_used <= shmem_size);
remaining_bytes = shared_buffer->metadata()->bytes_used;
memcpy(local.get(), shared->shared, sizeof(MessageBuffer::Metadata) + shared_buffer->metadata()->bytes_used); memcpy(local.get(), shared->shared, sizeof(MessageBuffer::Metadata) + shared_buffer->metadata()->bytes_used);
shared_buffer->metadata()->bytes_used = 0; shared_buffer->metadata()->bytes_used = 0;
shared_buffer->free_message()->ipc_id = IpcId::Invalid; shared_buffer->free_message()->ipc_id = IpcId::Invalid;
} }
std::vector<std::unique_ptr<IpcMessage>> result; // Parse blocks from shared memory.
for (JsonMessage* message : *local_buffer) { for (JsonMessage* message : *local_buffer) {
std::cerr << "Got message with payload_size=" << message->payload_size << std::endl; //std::cerr << "Got message with payload_size=" << message->payload_size << std::endl;
if (message->partial_message_id != 0) { if (message->partial_message_id != 0) {
auto* buf = CreateOrFindResizableBuffer(message->partial_message_id); auto* buf = CreateOrFindResizableBuffer(message->partial_message_id);
@ -346,21 +352,20 @@ std::vector<std::unique_ptr<IpcMessage>> IpcDirectionalChannel::TakeMessages() {
} }
local_buffer->metadata()->bytes_used = 0; local_buffer->metadata()->bytes_used = 0;
// Let other threads run. We still want to run as fast as possible, though.
std::this_thread::sleep_for(std::chrono::microseconds(0));
} while (resizable_buffers.size() > 0);
return result; return result;
} }
IpcServer::IpcServer(const std::string& name) IpcServer::IpcServer(const std::string& name, int client_id)
: name_(name), server_(NameToServerName(name)) {} : server_(NameToServerName(name)), client_(NameToClientName(name, client_id)) {}
void IpcServer::SendToClient(int client_id, IpcMessage* message) { void IpcServer::SendToClient(IpcMessage* message) {
// Find or create the client. client_.PushMessage(message);
auto it = clients_.find(client_id);
if (it == clients_.end())
clients_[client_id] = MakeUnique<IpcDirectionalChannel>(NameToClientName(name_, client_id));
clients_[client_id]->PushMessage(message);
} }
std::vector<std::unique_ptr<IpcMessage>> IpcServer::TakeMessages() { std::vector<std::unique_ptr<IpcMessage>> IpcServer::TakeMessages() {

10
ipc.h
View File

@ -23,6 +23,9 @@ enum class IpcId : int {
IsAlive, IsAlive,
OpenProject, OpenProject,
IndexTranslationUnitRequest,
IndexTranslationUnitResponse,
// This is a language server request. The actual request method // This is a language server request. The actual request method
// id is embedded within the request state. // id is embedded within the request state.
LanguageServerRequest, LanguageServerRequest,
@ -111,15 +114,14 @@ struct IpcDirectionalChannel {
}; };
struct IpcServer { struct IpcServer {
IpcServer(const std::string& name); IpcServer(const std::string& name, int client_id);
void SendToClient(int client_id, IpcMessage* message); void SendToClient(IpcMessage* message);
std::vector<std::unique_ptr<IpcMessage>> TakeMessages(); std::vector<std::unique_ptr<IpcMessage>> TakeMessages();
private: private:
std::string name_;
IpcDirectionalChannel server_; IpcDirectionalChannel server_;
std::unordered_map<int, std::unique_ptr<IpcDirectionalChannel>> clients_; IpcDirectionalChannel client_;
}; };
struct IpcClient { struct IpcClient {

View File

@ -14,7 +14,7 @@ struct PlatformSharedMemory {
void* shared; void* shared;
}; };
const int shmem_size = 200;// 1024 * 1024 * 32; // number of chars/bytes (32mb) const int shmem_size = 1024 * 1024 * 32; // number of chars/bytes (32mb)
std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name); std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name);
std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(PlatformMutex* mutex); std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(PlatformMutex* mutex);

91
query.h
View File

@ -59,6 +59,15 @@ struct QueryableLocation {
} }
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, QueryableLocation& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(path);
REFLECT_MEMBER(line);
REFLECT_MEMBER(column);
REFLECT_MEMBER(interesting);
REFLECT_MEMBER_END();
}
struct UsrRef { struct UsrRef {
Usr usr; Usr usr;
@ -76,7 +85,13 @@ struct UsrRef {
} }
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, UsrRef& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(usr);
REFLECT_MEMBER(loc);
REFLECT_MEMBER_END();
}
// There are two sources of reindex updates: the (single) definition of a // There are two sources of reindex updates: the (single) definition of a
// symbol has changed, or one of many users of the symbol has changed. // symbol has changed, or one of many users of the symbol has changed.
@ -96,10 +111,20 @@ struct MergeableUpdate {
std::vector<TValue> to_add; std::vector<TValue> to_add;
std::vector<TValue> to_remove; std::vector<TValue> to_remove;
MergeableUpdate() {} // For reflection
MergeableUpdate(Usr usr, const std::vector<TValue>& to_add, const std::vector<TValue>& to_remove) MergeableUpdate(Usr usr, const std::vector<TValue>& to_add, const std::vector<TValue>& to_remove)
: usr(usr), to_add(to_add), to_remove(to_remove) {} : usr(usr), to_add(to_add), to_remove(to_remove) {}
}; };
template<typename TVisitor, typename TValue>
void Reflect(TVisitor& visitor, MergeableUpdate<TValue>& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(usr);
REFLECT_MEMBER(to_add);
REFLECT_MEMBER(to_remove);
REFLECT_MEMBER_END();
}
struct QueryableFile { struct QueryableFile {
using OutlineUpdate = MergeableUpdate<UsrRef>; using OutlineUpdate = MergeableUpdate<UsrRef>;
@ -107,9 +132,18 @@ struct QueryableFile {
// Outline of the file (ie, all symbols). // Outline of the file (ie, all symbols).
std::vector<UsrRef> outline; std::vector<UsrRef> outline;
QueryableFile() {} // For serialization.
QueryableFile(const IndexedFile& indexed); QueryableFile(const IndexedFile& indexed);
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, QueryableFile& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(file_id);
REFLECT_MEMBER(outline);
REFLECT_MEMBER_END();
}
struct QueryableTypeDef { struct QueryableTypeDef {
using DefUpdate = TypeDefDefinitionData<Usr, Usr, Usr, QueryableLocation>; using DefUpdate = TypeDefDefinitionData<Usr, Usr, Usr, QueryableLocation>;
using DerivedUpdate = MergeableUpdate<Usr>; using DerivedUpdate = MergeableUpdate<Usr>;
@ -119,9 +153,19 @@ struct QueryableTypeDef {
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<QueryableLocation> uses; std::vector<QueryableLocation> uses;
QueryableTypeDef() : def("") {} // For serialization.
QueryableTypeDef(IdCache& id_cache, const IndexedTypeDef& indexed); QueryableTypeDef(IdCache& id_cache, const IndexedTypeDef& indexed);
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, QueryableTypeDef& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(def);
REFLECT_MEMBER(derived);
REFLECT_MEMBER(uses);
REFLECT_MEMBER_END();
}
struct QueryableFuncDef { struct QueryableFuncDef {
using DefUpdate = FuncDefDefinitionData<Usr, Usr, Usr, UsrRef, QueryableLocation>; using DefUpdate = FuncDefDefinitionData<Usr, Usr, Usr, UsrRef, QueryableLocation>;
using DeclarationsUpdate = MergeableUpdate<QueryableLocation>; using DeclarationsUpdate = MergeableUpdate<QueryableLocation>;
@ -135,9 +179,21 @@ struct QueryableFuncDef {
std::vector<UsrRef> callers; std::vector<UsrRef> callers;
std::vector<QueryableLocation> uses; std::vector<QueryableLocation> uses;
QueryableFuncDef() : def("") {} // For serialization.
QueryableFuncDef(IdCache& id_cache, const IndexedFuncDef& indexed); QueryableFuncDef(IdCache& id_cache, const IndexedFuncDef& indexed);
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, QueryableFuncDef& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(def);
REFLECT_MEMBER(declarations);
REFLECT_MEMBER(derived);
REFLECT_MEMBER(callers);
REFLECT_MEMBER(uses);
REFLECT_MEMBER_END();
}
struct QueryableVarDef { struct QueryableVarDef {
using DefUpdate = VarDefDefinitionData<Usr, Usr, Usr, QueryableLocation>; using DefUpdate = VarDefDefinitionData<Usr, Usr, Usr, QueryableLocation>;
using UsesUpdate = MergeableUpdate<QueryableLocation>; using UsesUpdate = MergeableUpdate<QueryableLocation>;
@ -145,9 +201,18 @@ struct QueryableVarDef {
DefUpdate def; DefUpdate def;
std::vector<QueryableLocation> uses; std::vector<QueryableLocation> uses;
QueryableVarDef() : def("") {} // For serialization.
QueryableVarDef(IdCache& id_cache, const IndexedVarDef& indexed); QueryableVarDef(IdCache& id_cache, const IndexedVarDef& indexed);
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, QueryableVarDef& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(def);
REFLECT_MEMBER(uses);
REFLECT_MEMBER_END();
}
enum class SymbolKind { Invalid, File, Type, Func, Var }; enum class SymbolKind { Invalid, File, Type, Func, Var };
struct SymbolIdx { struct SymbolIdx {
SymbolKind kind; SymbolKind kind;
@ -219,6 +284,30 @@ struct IndexUpdate {
void Merge(const IndexUpdate& update); void Merge(const IndexUpdate& update);
}; };
template<typename TVisitor>
void Reflect(TVisitor& visitor, IndexUpdate& value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(files_removed);
REFLECT_MEMBER(files_added);
REFLECT_MEMBER(files_outline);
REFLECT_MEMBER(types_removed);
REFLECT_MEMBER(types_added);
REFLECT_MEMBER(types_def_changed);
REFLECT_MEMBER(types_derived);
REFLECT_MEMBER(types_uses);
REFLECT_MEMBER(funcs_removed);
REFLECT_MEMBER(funcs_added);
REFLECT_MEMBER(funcs_def_changed);
REFLECT_MEMBER(funcs_declarations);
REFLECT_MEMBER(funcs_derived);
REFLECT_MEMBER(funcs_callers);
REFLECT_MEMBER(funcs_uses);
REFLECT_MEMBER(vars_removed);
REFLECT_MEMBER(vars_added);
REFLECT_MEMBER(vars_def_changed);
REFLECT_MEMBER(vars_uses);
REFLECT_MEMBER_END();
}
// The query database is heavily optimized for fast queries. It is stored // The query database is heavily optimized for fast queries. It is stored

View File

@ -1,5 +1,7 @@
#include "serializer.h" #include "serializer.h"
#include "indexer.h"
// int // int
void Reflect(Reader& visitor, int& value) { void Reflect(Reader& visitor, int& value) {

View File

@ -2,8 +2,13 @@
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include <rapidjson/prettywriter.h> #include <rapidjson/prettywriter.h>
#include <vector>
#include <string>
#include "indexer.h" #include "optional.h"
using std::experimental::optional;
using std::experimental::nullopt;
using Reader = rapidjson::GenericValue<rapidjson::UTF8<>>; using Reader = rapidjson::GenericValue<rapidjson::UTF8<>>;
using Writer = rapidjson::PrettyWriter<rapidjson::StringBuffer>; using Writer = rapidjson::PrettyWriter<rapidjson::StringBuffer>;