Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Unified Diff: runtime/bin/vmstats_impl.cc

Issue 18611003: Remove VM Stats (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/vmstats_impl.h ('k') | runtime/bin/vmstats_impl_android.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/vmstats_impl.cc
diff --git a/runtime/bin/vmstats_impl.cc b/runtime/bin/vmstats_impl.cc
deleted file mode 100644
index b3eebff2ba390a0f1f9523ff7fb6e4fea63a5894..0000000000000000000000000000000000000000
--- a/runtime/bin/vmstats_impl.cc
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "bin/vmstats_impl.h"
-
-#include "bin/file.h"
-#include "bin/log.h"
-#include "bin/platform.h"
-#include "bin/resources.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-#include "include/dart_debugger_api.h"
-#include "platform/json.h"
-
-
-namespace dart {
-namespace bin {
-
-#define BUFSIZE 8192
-#define RETRY_PAUSE 100 // milliseconds
-
-static const char* INDEX_HTML = "index.html";
-static const char* VMSTATS_HTML = "vmstats.html";
-static const char* DEFAULT_HOST = "localhost";
-
-// Global static pointer used to ensure a single instance of the class.
-VmStats* VmStats::instance_ = NULL;
-dart::Monitor* VmStats::instance_monitor_;
-dart::Mutex* VmStatusService::mutex_;
-
-
-void VmStats::Start(int port, const char* root_dir, bool verbose) {
- if (instance_ != NULL) {
- FATAL("VmStats already started.");
- }
- instance_ = new VmStats(verbose);
- instance_monitor_ = new dart::Monitor();
- Initialize();
- VmStatusService::InitOnce();
-
- if (port >= 0) {
- StartServer(port, root_dir);
- }
-}
-
-
-void VmStats::StartServer(int port, const char* root_dir) {
- ASSERT(port >= 0);
- ASSERT(instance_ != NULL);
- ASSERT(instance_monitor_ != NULL);
- Socket::Initialize();
-
- if (root_dir != NULL) {
- instance_->root_directory_ = root_dir;
- }
-
- // TODO(tball): allow host to be specified.
- char* host = const_cast<char*>(DEFAULT_HOST);
- OSError* os_error;
- AddressList<SocketAddress>* addresses =
- Socket::LookupAddress(host, -1, &os_error);
- if (addresses == NULL) {
- Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n",
- host, os_error->message());
- return;
- }
- const intptr_t BACKLOG = 128; // Default value from HttpServer.dart
- int64_t address = ServerSocket::CreateBindListen(
- addresses->GetAt(0)->addr(), port, BACKLOG);
- delete addresses;
- if (address < 0) {
- Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port);
- return;
- }
- instance_->bind_address_ = address;
- Log::Print("VmStats URL: http://%s:%"Pd"/\n", host, Socket::GetPort(address));
-
- MonitorLocker ml(instance_monitor_);
- instance_->running_ = true;
- int err = dart::Thread::Start(WebServer, address);
- if (err != 0) {
- Log::PrintErr("Failed starting VmStats thread: %d\n", err);
- Shutdown();
- }
-}
-
-void VmStats::Stop() {
- ASSERT(instance_ != NULL);
- MonitorLocker ml(instance_monitor_);
- instance_->running_ = false;
-}
-
-
-void VmStats::Shutdown() {
- ASSERT(instance_ != NULL);
- MonitorLocker ml(instance_monitor_);
- Socket::Close(instance_->bind_address_);
- delete instance_;
- instance_ = NULL;
-}
-
-
-void VmStats::AddIsolate(IsolateData* isolate_data,
- Dart_Isolate isolate) {
- MonitorLocker ml(instance_monitor_);
- instance_->isolate_table_[isolate_data] = isolate;
-}
-
-
-void VmStats::RemoveIsolate(IsolateData* isolate_data) {
- MonitorLocker ml(instance_monitor_);
- instance_->isolate_table_.erase(isolate_data);
-}
-
-
-static const char* ContentType(const char* url) {
- const char* suffix = strrchr(url, '.');
- if (suffix != NULL) {
- if (!strcmp(suffix, ".html")) {
- return "text/html; charset=UTF-8";
- }
- if (!strcmp(suffix, ".dart")) {
- return "application/dart; charset=UTF-8";
- }
- if (!strcmp(suffix, ".js")) {
- return "application/javascript; charset=UTF-8";
- }
- if (!strcmp(suffix, ".css")) {
- return "text/css; charset=UTF-8";
- }
- if (!strcmp(suffix, ".gif")) {
- return "image/gif";
- }
- if (!strcmp(suffix, ".png")) {
- return "image/png";
- }
- if (!strcmp(suffix, ".jpg") || !strcmp(suffix, ".jpeg")) {
- return "image/jpeg";
- }
- }
- return "text/plain";
-}
-
-
-// Return a malloc'd string from a format string and arguments.
-intptr_t alloc_printf(char** result, const char* format, ...) {
- va_list args;
- va_start(args, format);
- intptr_t len = vsnprintf(NULL, 0, format, args) + 1;
- *result = reinterpret_cast<char*>(malloc(len));
- return vsnprintf(*result, len, format, args);
-}
-
-
-void writeResponse(intptr_t socket, const char* content_type,
- const char* data, size_t length) {
- char* header;
- intptr_t len = alloc_printf(&header,
- "HTTP/1.1 200 OK\nContent-Type: %s\nContent-Length: %"Pu"\n\n",
- content_type, length);
- Socket::Write(socket, header, len);
- Socket::Write(socket, data, length);
- Socket::Write(socket, "\n", 1);
- free(header);
-}
-
-
-void writeErrorResponse(intptr_t socket, intptr_t error_num, const char* error,
- const char* description) {
- if (description != NULL) {
- // Create body first, so its length is known when creating the header.
- char* body;
- intptr_t body_len = alloc_printf(&body,
- "<html><head><title>%d %s</title></head>\n"
- "<body>\n<h1>%s</h1>\n%s\n</body></html>\n",
- error_num, error, error, description);
- char* header;
- intptr_t header_len = alloc_printf(&header,
- "HTTP/1.1 %d %s\n"
- "Content-Length: %d\n"
- "Connection: close\n"
- "Content-Type: text/html\n\n",
- error_num, error, body_len);
- Socket::Write(socket, header, header_len);
- Socket::Write(socket, body, body_len);
- free(header);
- free(body);
- } else {
- char* response;
- intptr_t len =
- alloc_printf(&response, "HTTP/1.1 %d %s\n\n", error_num, error);
- Socket::Write(socket, response, len);
- free(response);
- }
-}
-
-
-void VmStats::WebServer(uword bind_address) {
- while (true) {
- intptr_t socket = ServerSocket::Accept(bind_address);
- if (socket == ServerSocket::kTemporaryFailure) {
- // Not a real failure, woke up but no connection available.
-
- // Use MonitorLocker.Wait(), since it has finer granularity than sleep().
- dart::Monitor m;
- MonitorLocker ml(&m);
- ml.Wait(RETRY_PAUSE);
-
- continue;
- }
- if (socket < 0) {
- // Stop() closed the socket.
- return;
- }
- Socket::SetBlocking(socket);
-
- // TODO(tball): rewrite this to use STL, so as to eliminate the static
- // buffer and support resource URLs that are longer than BUFSIZE.
-
- // Read request.
- char buffer[BUFSIZE + 1];
- intptr_t len = Socket::Read(socket, buffer, BUFSIZE);
- if (len <= 0) {
- // Invalid HTTP request, ignore.
- continue;
- }
- buffer[len] = '\0';
-
- // Verify it's a GET request.
- // TODO(tball): support POST requests.
- if (strncmp("GET ", buffer, 4) != 0 && strncmp("get ", buffer, 4) != 0) {
- Log::PrintErr("Unsupported HTTP request type");
- writeErrorResponse(socket, 403, "Forbidden",
- "Unsupported HTTP request type");
- Socket::Close(socket);
- continue;
- }
-
- // Extract GET URL, and null-terminate URL in case request line has
- // HTTP version.
- for (int i = 4; i < len; i++) {
- if (buffer[i] == ' ') {
- buffer[i] = '\0';
- }
- }
- char* url = strdup(&buffer[4]);
-
- if (instance_->verbose_) {
- Log::Print("vmstats: %s requested\n", url);
- }
- char* content = NULL;
-
- // Check for VmStats-specific URLs.
- if (strcmp(url, "/isolates") == 0) {
- content = instance_->IsolatesStatus();
- } else {
- // Check plug-ins.
- content = VmStatusService::GetVmStatus(url);
- }
-
- if (content != NULL) {
- writeResponse(socket, "application/json", content, strlen(content));
- free(content);
- } else {
- // No status content with this URL, return file or resource content.
- dart::TextBuffer path(strlen(instance_->root_directory_) + strlen(url));
- path.AddString(instance_->root_directory_);
- path.AddString(url);
-
- // Expand directory URLs.
- if (strcmp(url, "/") == 0) {
- path.AddString(VMSTATS_HTML);
- } else if (url[strlen(url) - 1] == '/') {
- path.AddString(INDEX_HTML);
- }
-
- bool success = false;
- char* text_buffer = NULL;
- const char* content_type = ContentType(path.buf());
- if (File::Exists(path.buf())) {
- File* f = File::Open(path.buf(), File::kRead);
- if (f != NULL) {
- intptr_t len = f->Length();
- text_buffer = reinterpret_cast<char*>(malloc(len));
- if (f->ReadFully(text_buffer, len)) {
- writeResponse(socket, content_type, text_buffer, len);
- success = true;
- }
- free(text_buffer);
- delete f;
- }
- } else {
- const char* resource;
- intptr_t len = Resources::ResourceLookup(path.buf(), &resource);
- if (len != Resources::kNoSuchInstance) {
- ASSERT(len >= 0);
- writeResponse(socket, content_type, resource, len);
- success = true;
- }
- }
- if (!success) {
- char* description;
- alloc_printf(
- &description, "URL <a href=\"%s\">%s</a> not found.", url, url);
- writeErrorResponse(socket, 404, "Not Found", description);
- free(description);
- }
- }
- Socket::Close(socket);
- free(url);
- }
-
- Shutdown();
-}
-
-
-char* VmStats::IsolatesStatus() {
- dart::TextBuffer text(64);
- text.Printf("{\n\"isolates\": [\n");
- IsolateTable::iterator itr;
- bool first = true;
- for (itr = isolate_table_.begin(); itr != isolate_table_.end(); ++itr) {
- Dart_Isolate isolate = itr->second;
- static char request[512];
- snprintf(request, sizeof(request),
- "/isolate/0x%"Px,
- reinterpret_cast<intptr_t>(isolate));
- char* status = VmStatusService::GetVmStatus(request);
- if (status != NULL) {
- if (!first) {
- text.AddString(",\n");
- }
- text.AddString(status);
- first = false;
- free(status);
- }
- }
- text.AddString("\n]\n}\n");
- return strdup(text.buf());
-}
-
-
-// Advance the scanner to the value token of a specified name-value pair.
-void SeekNamedValue(const char* name, dart::JSONScanner* scanner) {
- while (!scanner->EOM()) {
- scanner->Scan();
- if (scanner->IsStringLiteral(name)) {
- scanner->Scan();
- ASSERT(scanner->CurrentToken() == dart::JSONScanner::TokenColon);
- scanner->Scan();
- return;
- }
- }
-}
-
-
-// Windows doesn't have strndup(), so this is a simple, private version.
-static char* StrNDup(const char* s, uword len) {
- if (strlen(s) < len) {
- len = strlen(s);
- }
- char* result = reinterpret_cast<char*>(malloc(len + 1));
- memmove(result, s, len);
- result[len + 1] = '\0';
- return result;
-}
-
-
-void VmStats::DumpStackThread(uword unused) {
- Log::Print("Isolate dump:\n");
- IsolateTable::iterator itr;
- MonitorLocker ml(instance_monitor_);
- for (itr = instance_->isolate_table_.begin();
- itr != instance_->isolate_table_.end(); ++itr) {
- Dart_Isolate isolate = itr->second;
-
- // Print isolate name and details.
- static char buffer[512];
- snprintf(buffer, sizeof(buffer),
- "/isolate/0x%"Px, reinterpret_cast<intptr_t>(isolate));
- char* isolate_details = VmStatusService::GetVmStatus(buffer);
- if (isolate_details != NULL) {
- dart::JSONScanner scanner(isolate_details);
- SeekNamedValue("name", &scanner);
- char* name = StrNDup(scanner.TokenChars(), scanner.TokenLen());
- SeekNamedValue("port", &scanner);
- char* port = StrNDup(scanner.TokenChars(), scanner.TokenLen());
- Log::Print("\"%s\" port=%s\n", name, port);
- free(isolate_details);
- free(port);
- free(name);
- }
-
- // Print stack trace.
- snprintf(buffer, sizeof(buffer),
- "/isolate/0x%"Px"/stacktrace",
- reinterpret_cast<intptr_t>(isolate));
- char* trace = VmStatusService::GetVmStatus(buffer);
- if (trace != NULL) {
- dart::JSONScanner scanner(trace);
- while (true) {
- SeekNamedValue("url", &scanner);
- if (scanner.CurrentToken() == dart::JSONScanner::TokenEOM) {
- break;
- }
- char* url = StrNDup(scanner.TokenChars(), scanner.TokenLen());
- SeekNamedValue("line", &scanner);
- char* line = StrNDup(scanner.TokenChars(), scanner.TokenLen());
- SeekNamedValue("function", &scanner);
- char* function = StrNDup(scanner.TokenChars(), scanner.TokenLen());
- Log::Print(" at %s(%s:%s)\n", function, url, line);
- free(url);
- free(line);
- free(function);
- }
- free(trace);
- }
- }
-}
-
-
-void VmStats::DumpStack() {
- int err = dart::Thread::Start(DumpStackThread, 0);
- if (err != 0) {
- Log::PrintErr("Failed starting VmStats stackdump thread: %d\n", err);
- Shutdown();
- }
-}
-
-
-// Global static pointer used to ensure a single instance of the class.
-VmStatusService* VmStatusService::instance_ = NULL;
-
-
-void VmStatusService::InitOnce() {
- ASSERT(VmStatusService::instance_ == NULL);
- VmStatusService::instance_ = new VmStatusService();
- VmStatusService::mutex_ = new dart::Mutex();
-
- // Register built-in status plug-ins. RegisterPlugin is not used because
- // this isn't called within an isolate, and because parameter checking
- // isn't necessary.
- instance_->RegisterPlugin(&Dart_GetVmStatus);
-
- // TODO(tball): dynamically load any additional plug-ins.
-}
-
-
-int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) {
- ASSERT(VmStatusService::instance_ != NULL);
- ASSERT(VmStatusService::mutex_ != NULL);
- MutexLocker ml(mutex_);
- if (callback == NULL) {
- return -1;
- }
- VmStatusPlugin* plugin = new VmStatusPlugin(callback);
- VmStatusPlugin* list = instance_->registered_plugin_list_;
- if (list == NULL) {
- instance_->registered_plugin_list_ = plugin;
- } else {
- list->Append(plugin);
- }
- return 0;
-}
-
-
-char* VmStatusService::GetVmStatus(const char* request) {
- ASSERT(VmStatusService::instance_ != NULL);
- VmStatusPlugin* plugin = instance_->registered_plugin_list_;
- while (plugin != NULL) {
- char* result = (plugin->callback())(request);
- if (result != NULL) {
- return result;
- }
- plugin = plugin->next();
- }
- return NULL;
-}
-
-} // namespace bin
-} // namespace dart
« no previous file with comments | « runtime/bin/vmstats_impl.h ('k') | runtime/bin/vmstats_impl_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698