Add 'Flog' formatted logging to mojo/services Introduces service definitions for 'Flog' (formatting logging) and associated C++ library for adding log generation to services and applications. No logging service is implemented yet, just the stuff needed to annotate code that needs to generate log messages. R=kulakowski@chromium.org Review URL: https://codereview.chromium.org/2008553006 .
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/flog/flog.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/flog/flog.mojom.dart new file mode 100644 index 0000000..738b2fc --- /dev/null +++ b/mojo/dart/packages/mojo_services/lib/mojo/flog/flog.mojom.dart
@@ -0,0 +1,2164 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +library flog_mojom; +import 'dart:async'; +import 'package:mojo/bindings.dart' as bindings; +import 'package:mojo/core.dart' as core; +import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer; + + + +class FlogDescription extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(48, 0) + ]; + String label = null; + int logId = 0; + int entryCount = 0; + int startTimeUs = 0; + int stopTimeUs = 0; + bool open = false; + + FlogDescription() : super(kVersions.last.size); + + static FlogDescription deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static FlogDescription decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + FlogDescription result = new FlogDescription(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.label = decoder0.decodeString(8, false); + } + if (mainDataHeader.version >= 0) { + + result.logId = decoder0.decodeUint32(16); + } + if (mainDataHeader.version >= 0) { + + result.entryCount = decoder0.decodeUint32(20); + } + if (mainDataHeader.version >= 0) { + + result.startTimeUs = decoder0.decodeInt64(24); + } + if (mainDataHeader.version >= 0) { + + result.stopTimeUs = decoder0.decodeInt64(32); + } + if (mainDataHeader.version >= 0) { + + result.open = decoder0.decodeBool(40, 0); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeString(label, 8, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "label of struct FlogDescription: $e"; + rethrow; + } + try { + encoder0.encodeUint32(logId, 16); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "logId of struct FlogDescription: $e"; + rethrow; + } + try { + encoder0.encodeUint32(entryCount, 20); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "entryCount of struct FlogDescription: $e"; + rethrow; + } + try { + encoder0.encodeInt64(startTimeUs, 24); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "startTimeUs of struct FlogDescription: $e"; + rethrow; + } + try { + encoder0.encodeInt64(stopTimeUs, 32); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "stopTimeUs of struct FlogDescription: $e"; + rethrow; + } + try { + encoder0.encodeBool(open, 40, 0); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "open of struct FlogDescription: $e"; + rethrow; + } + } + + String toString() { + return "FlogDescription(" + "label: $label" ", " + "logId: $logId" ", " + "entryCount: $entryCount" ", " + "startTimeUs: $startTimeUs" ", " + "stopTimeUs: $stopTimeUs" ", " + "open: $open" ")"; + } + + Map toJson() { + Map map = new Map(); + map["label"] = label; + map["logId"] = logId; + map["entryCount"] = entryCount; + map["startTimeUs"] = startTimeUs; + map["stopTimeUs"] = stopTimeUs; + map["open"] = open; + return map; + } +} + + +class FlogEntry extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(40, 0) + ]; + int timeUs = 0; + int logId = 0; + int channelId = 0; + FlogEntryDetails details = null; + + FlogEntry() : super(kVersions.last.size); + + static FlogEntry deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static FlogEntry decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + FlogEntry result = new FlogEntry(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.timeUs = decoder0.decodeInt64(8); + } + if (mainDataHeader.version >= 0) { + + result.logId = decoder0.decodeUint32(16); + } + if (mainDataHeader.version >= 0) { + + result.channelId = decoder0.decodeUint32(20); + } + if (mainDataHeader.version >= 0) { + + result.details = FlogEntryDetails.decode(decoder0, 24); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeInt64(timeUs, 8); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "timeUs of struct FlogEntry: $e"; + rethrow; + } + try { + encoder0.encodeUint32(logId, 16); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "logId of struct FlogEntry: $e"; + rethrow; + } + try { + encoder0.encodeUint32(channelId, 20); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "channelId of struct FlogEntry: $e"; + rethrow; + } + try { + encoder0.encodeUnion(details, 24, true); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "details of struct FlogEntry: $e"; + rethrow; + } + } + + String toString() { + return "FlogEntry(" + "timeUs: $timeUs" ", " + "logId: $logId" ", " + "channelId: $channelId" ", " + "details: $details" ")"; + } + + Map toJson() { + Map map = new Map(); + map["timeUs"] = timeUs; + map["logId"] = logId; + map["channelId"] = channelId; + map["details"] = details; + return map; + } +} + + +class FlogChannelCreationEntryDetails extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(16, 0) + ]; + String typeName = null; + + FlogChannelCreationEntryDetails() : super(kVersions.last.size); + + static FlogChannelCreationEntryDetails deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static FlogChannelCreationEntryDetails decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + FlogChannelCreationEntryDetails result = new FlogChannelCreationEntryDetails(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.typeName = decoder0.decodeString(8, false); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeString(typeName, 8, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "typeName of struct FlogChannelCreationEntryDetails: $e"; + rethrow; + } + } + + String toString() { + return "FlogChannelCreationEntryDetails(" + "typeName: $typeName" ")"; + } + + Map toJson() { + Map map = new Map(); + map["typeName"] = typeName; + return map; + } +} + + +class FlogChannelMessageEntryDetails extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(16, 0) + ]; + List<int> data = null; + + FlogChannelMessageEntryDetails() : super(kVersions.last.size); + + static FlogChannelMessageEntryDetails deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static FlogChannelMessageEntryDetails decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + FlogChannelMessageEntryDetails result = new FlogChannelMessageEntryDetails(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.data = decoder0.decodeUint8Array(8, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeUint8Array(data, 8, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "data of struct FlogChannelMessageEntryDetails: $e"; + rethrow; + } + } + + String toString() { + return "FlogChannelMessageEntryDetails(" + "data: $data" ")"; + } + + Map toJson() { + Map map = new Map(); + map["data"] = data; + return map; + } +} + + +class _FlogServiceCreateLoggerParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(24, 0) + ]; + FlogLoggerInterfaceRequest logger = null; + String label = null; + + _FlogServiceCreateLoggerParams() : super(kVersions.last.size); + + static _FlogServiceCreateLoggerParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogServiceCreateLoggerParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogServiceCreateLoggerParams result = new _FlogServiceCreateLoggerParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.logger = decoder0.decodeInterfaceRequest(8, false, FlogLoggerStub.newFromEndpoint); + } + if (mainDataHeader.version >= 0) { + + result.label = decoder0.decodeString(16, false); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeInterfaceRequest(logger, 8, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "logger of struct _FlogServiceCreateLoggerParams: $e"; + rethrow; + } + try { + encoder0.encodeString(label, 16, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "label of struct _FlogServiceCreateLoggerParams: $e"; + rethrow; + } + } + + String toString() { + return "_FlogServiceCreateLoggerParams(" + "logger: $logger" ", " + "label: $label" ")"; + } + + Map toJson() { + throw new bindings.MojoCodecError( + 'Object containing handles cannot be encoded to JSON.'); + } +} + + +class _FlogServiceGetLogDescriptionsParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(8, 0) + ]; + + _FlogServiceGetLogDescriptionsParams() : super(kVersions.last.size); + + static _FlogServiceGetLogDescriptionsParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogServiceGetLogDescriptionsParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogServiceGetLogDescriptionsParams result = new _FlogServiceGetLogDescriptionsParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + return result; + } + + void encode(bindings.Encoder encoder) { + encoder.getStructEncoderAtOffset(kVersions.last); + } + + String toString() { + return "_FlogServiceGetLogDescriptionsParams("")"; + } + + Map toJson() { + Map map = new Map(); + return map; + } +} + + +class FlogServiceGetLogDescriptionsResponseParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(16, 0) + ]; + List<FlogDescription> descriptions = null; + + FlogServiceGetLogDescriptionsResponseParams() : super(kVersions.last.size); + + static FlogServiceGetLogDescriptionsResponseParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static FlogServiceGetLogDescriptionsResponseParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + FlogServiceGetLogDescriptionsResponseParams result = new FlogServiceGetLogDescriptionsResponseParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + var decoder1 = decoder0.decodePointer(8, false); + { + var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength); + result.descriptions = new List<FlogDescription>(si1.numElements); + for (int i1 = 0; i1 < si1.numElements; ++i1) { + + var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false); + result.descriptions[i1] = FlogDescription.decode(decoder2); + } + } + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + if (descriptions == null) { + encoder0.encodeNullPointer(8, false); + } else { + var encoder1 = encoder0.encodePointerArray(descriptions.length, 8, bindings.kUnspecifiedArrayLength); + for (int i0 = 0; i0 < descriptions.length; ++i0) { + encoder1.encodeStruct(descriptions[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false); + } + } + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "descriptions of struct FlogServiceGetLogDescriptionsResponseParams: $e"; + rethrow; + } + } + + String toString() { + return "FlogServiceGetLogDescriptionsResponseParams(" + "descriptions: $descriptions" ")"; + } + + Map toJson() { + Map map = new Map(); + map["descriptions"] = descriptions; + return map; + } +} + + +class _FlogServiceCreateReaderParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(16, 0) + ]; + FlogReaderInterfaceRequest reader = null; + int logId = 0; + + _FlogServiceCreateReaderParams() : super(kVersions.last.size); + + static _FlogServiceCreateReaderParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogServiceCreateReaderParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogServiceCreateReaderParams result = new _FlogServiceCreateReaderParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.reader = decoder0.decodeInterfaceRequest(8, false, FlogReaderStub.newFromEndpoint); + } + if (mainDataHeader.version >= 0) { + + result.logId = decoder0.decodeUint32(12); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeInterfaceRequest(reader, 8, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "reader of struct _FlogServiceCreateReaderParams: $e"; + rethrow; + } + try { + encoder0.encodeUint32(logId, 12); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "logId of struct _FlogServiceCreateReaderParams: $e"; + rethrow; + } + } + + String toString() { + return "_FlogServiceCreateReaderParams(" + "reader: $reader" ", " + "logId: $logId" ")"; + } + + Map toJson() { + throw new bindings.MojoCodecError( + 'Object containing handles cannot be encoded to JSON.'); + } +} + + +class _FlogLoggerLogChannelCreationParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(32, 0) + ]; + int timeUs = 0; + int channelId = 0; + String typeName = null; + + _FlogLoggerLogChannelCreationParams() : super(kVersions.last.size); + + static _FlogLoggerLogChannelCreationParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogLoggerLogChannelCreationParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogLoggerLogChannelCreationParams result = new _FlogLoggerLogChannelCreationParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.timeUs = decoder0.decodeInt64(8); + } + if (mainDataHeader.version >= 0) { + + result.channelId = decoder0.decodeUint32(16); + } + if (mainDataHeader.version >= 0) { + + result.typeName = decoder0.decodeString(24, false); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeInt64(timeUs, 8); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "timeUs of struct _FlogLoggerLogChannelCreationParams: $e"; + rethrow; + } + try { + encoder0.encodeUint32(channelId, 16); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "channelId of struct _FlogLoggerLogChannelCreationParams: $e"; + rethrow; + } + try { + encoder0.encodeString(typeName, 24, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "typeName of struct _FlogLoggerLogChannelCreationParams: $e"; + rethrow; + } + } + + String toString() { + return "_FlogLoggerLogChannelCreationParams(" + "timeUs: $timeUs" ", " + "channelId: $channelId" ", " + "typeName: $typeName" ")"; + } + + Map toJson() { + Map map = new Map(); + map["timeUs"] = timeUs; + map["channelId"] = channelId; + map["typeName"] = typeName; + return map; + } +} + + +class _FlogLoggerLogChannelMessageParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(32, 0) + ]; + int timeUs = 0; + int channelId = 0; + List<int> data = null; + + _FlogLoggerLogChannelMessageParams() : super(kVersions.last.size); + + static _FlogLoggerLogChannelMessageParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogLoggerLogChannelMessageParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogLoggerLogChannelMessageParams result = new _FlogLoggerLogChannelMessageParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.timeUs = decoder0.decodeInt64(8); + } + if (mainDataHeader.version >= 0) { + + result.channelId = decoder0.decodeUint32(16); + } + if (mainDataHeader.version >= 0) { + + result.data = decoder0.decodeUint8Array(24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeInt64(timeUs, 8); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "timeUs of struct _FlogLoggerLogChannelMessageParams: $e"; + rethrow; + } + try { + encoder0.encodeUint32(channelId, 16); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "channelId of struct _FlogLoggerLogChannelMessageParams: $e"; + rethrow; + } + try { + encoder0.encodeUint8Array(data, 24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "data of struct _FlogLoggerLogChannelMessageParams: $e"; + rethrow; + } + } + + String toString() { + return "_FlogLoggerLogChannelMessageParams(" + "timeUs: $timeUs" ", " + "channelId: $channelId" ", " + "data: $data" ")"; + } + + Map toJson() { + Map map = new Map(); + map["timeUs"] = timeUs; + map["channelId"] = channelId; + map["data"] = data; + return map; + } +} + + +class _FlogLoggerLogChannelDeletionParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(24, 0) + ]; + int timeUs = 0; + int channelId = 0; + + _FlogLoggerLogChannelDeletionParams() : super(kVersions.last.size); + + static _FlogLoggerLogChannelDeletionParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogLoggerLogChannelDeletionParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogLoggerLogChannelDeletionParams result = new _FlogLoggerLogChannelDeletionParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.timeUs = decoder0.decodeInt64(8); + } + if (mainDataHeader.version >= 0) { + + result.channelId = decoder0.decodeUint32(16); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeInt64(timeUs, 8); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "timeUs of struct _FlogLoggerLogChannelDeletionParams: $e"; + rethrow; + } + try { + encoder0.encodeUint32(channelId, 16); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "channelId of struct _FlogLoggerLogChannelDeletionParams: $e"; + rethrow; + } + } + + String toString() { + return "_FlogLoggerLogChannelDeletionParams(" + "timeUs: $timeUs" ", " + "channelId: $channelId" ")"; + } + + Map toJson() { + Map map = new Map(); + map["timeUs"] = timeUs; + map["channelId"] = channelId; + return map; + } +} + + +class _FlogReaderGetEntriesParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(16, 0) + ]; + int startIndex = 0; + int maxCount = 0; + + _FlogReaderGetEntriesParams() : super(kVersions.last.size); + + static _FlogReaderGetEntriesParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static _FlogReaderGetEntriesParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + _FlogReaderGetEntriesParams result = new _FlogReaderGetEntriesParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.startIndex = decoder0.decodeUint32(8); + } + if (mainDataHeader.version >= 0) { + + result.maxCount = decoder0.decodeUint32(12); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeUint32(startIndex, 8); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "startIndex of struct _FlogReaderGetEntriesParams: $e"; + rethrow; + } + try { + encoder0.encodeUint32(maxCount, 12); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "maxCount of struct _FlogReaderGetEntriesParams: $e"; + rethrow; + } + } + + String toString() { + return "_FlogReaderGetEntriesParams(" + "startIndex: $startIndex" ", " + "maxCount: $maxCount" ")"; + } + + Map toJson() { + Map map = new Map(); + map["startIndex"] = startIndex; + map["maxCount"] = maxCount; + return map; + } +} + + +class FlogReaderGetEntriesResponseParams extends bindings.Struct { + static const List<bindings.StructDataHeader> kVersions = const [ + const bindings.StructDataHeader(24, 0) + ]; + List<FlogEntry> entries = null; + int entryCount = 0; + bool open = false; + + FlogReaderGetEntriesResponseParams() : super(kVersions.last.size); + + static FlogReaderGetEntriesResponseParams deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static FlogReaderGetEntriesResponseParams decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + FlogReaderGetEntriesResponseParams result = new FlogReaderGetEntriesResponseParams(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + var decoder1 = decoder0.decodePointer(8, false); + { + var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength); + result.entries = new List<FlogEntry>(si1.numElements); + for (int i1 = 0; i1 < si1.numElements; ++i1) { + + var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false); + result.entries[i1] = FlogEntry.decode(decoder2); + } + } + } + if (mainDataHeader.version >= 0) { + + result.entryCount = decoder0.decodeUint32(16); + } + if (mainDataHeader.version >= 0) { + + result.open = decoder0.decodeBool(20, 0); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + if (entries == null) { + encoder0.encodeNullPointer(8, false); + } else { + var encoder1 = encoder0.encodePointerArray(entries.length, 8, bindings.kUnspecifiedArrayLength); + for (int i0 = 0; i0 < entries.length; ++i0) { + encoder1.encodeStruct(entries[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false); + } + } + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "entries of struct FlogReaderGetEntriesResponseParams: $e"; + rethrow; + } + try { + encoder0.encodeUint32(entryCount, 16); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "entryCount of struct FlogReaderGetEntriesResponseParams: $e"; + rethrow; + } + try { + encoder0.encodeBool(open, 20, 0); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "open of struct FlogReaderGetEntriesResponseParams: $e"; + rethrow; + } + } + + String toString() { + return "FlogReaderGetEntriesResponseParams(" + "entries: $entries" ", " + "entryCount: $entryCount" ", " + "open: $open" ")"; + } + + Map toJson() { + Map map = new Map(); + map["entries"] = entries; + map["entryCount"] = entryCount; + map["open"] = open; + return map; + } +} + + + +enum FlogEntryDetailsTag { + channelCreation, + channelMessage, + unknown +} + +class FlogEntryDetails extends bindings.Union { + static final _tagToInt = const { + FlogEntryDetailsTag.channelCreation: 0, + FlogEntryDetailsTag.channelMessage: 1, + }; + + static final _intToTag = const { + 0: FlogEntryDetailsTag.channelCreation, + 1: FlogEntryDetailsTag.channelMessage, + }; + + var _data; + FlogEntryDetailsTag _tag = FlogEntryDetailsTag.unknown; + + FlogEntryDetailsTag get tag => _tag; + FlogChannelCreationEntryDetails get channelCreation { + if (_tag != FlogEntryDetailsTag.channelCreation) { + throw new bindings.UnsetUnionTagError(_tag, FlogEntryDetailsTag.channelCreation); + } + return _data; + } + + set channelCreation(FlogChannelCreationEntryDetails value) { + _tag = FlogEntryDetailsTag.channelCreation; + _data = value; + } + FlogChannelMessageEntryDetails get channelMessage { + if (_tag != FlogEntryDetailsTag.channelMessage) { + throw new bindings.UnsetUnionTagError(_tag, FlogEntryDetailsTag.channelMessage); + } + return _data; + } + + set channelMessage(FlogChannelMessageEntryDetails value) { + _tag = FlogEntryDetailsTag.channelMessage; + _data = value; + } + + static FlogEntryDetails decode(bindings.Decoder decoder0, int offset) { + int size = decoder0.decodeUint32(offset); + if (size == 0) { + return null; + } + FlogEntryDetails result = new FlogEntryDetails(); + + + FlogEntryDetailsTag tag = _intToTag[decoder0.decodeUint32(offset + 4)]; + switch (tag) { + case FlogEntryDetailsTag.channelCreation: + + var decoder1 = decoder0.decodePointer(offset + 8, false); + result.channelCreation = FlogChannelCreationEntryDetails.decode(decoder1); + break; + case FlogEntryDetailsTag.channelMessage: + + var decoder1 = decoder0.decodePointer(offset + 8, false); + result.channelMessage = FlogChannelMessageEntryDetails.decode(decoder1); + break; + default: + throw new bindings.MojoCodecError("Bad union tag: $tag"); + } + + return result; + } + + void encode(bindings.Encoder encoder0, int offset) { + + encoder0.encodeUint32(16, offset); + encoder0.encodeUint32(_tagToInt[_tag], offset + 4); + switch (_tag) { + case FlogEntryDetailsTag.channelCreation: + encoder0.encodeStruct(channelCreation, offset + 8, false); + break; + case FlogEntryDetailsTag.channelMessage: + encoder0.encodeStruct(channelMessage, offset + 8, false); + break; + default: + throw new bindings.MojoCodecError("Bad union tag: $_tag"); + } + } + + String toString() { + String result = "FlogEntryDetails("; + switch (_tag) { + case FlogEntryDetailsTag.channelCreation: + result += "channelCreation"; + break; + case FlogEntryDetailsTag.channelMessage: + result += "channelMessage"; + break; + default: + result += "unknown"; + } + result += ": $_data)"; + return result; + } +} +const int _flogServiceMethodCreateLoggerName = 0; +const int _flogServiceMethodGetLogDescriptionsName = 1; +const int _flogServiceMethodCreateReaderName = 2; + +class _FlogServiceServiceDescription implements service_describer.ServiceDescription { + dynamic getTopLevelInterface([Function responseFactory]) => + responseFactory(null); + + dynamic getTypeDefinition(String typeKey, [Function responseFactory]) => + responseFactory(null); + + dynamic getAllTypeDefinitions([Function responseFactory]) => + responseFactory(null); +} + +abstract class FlogService { + static const String serviceName = "mojo::flog::FlogService"; + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _FlogServiceServiceDescription(); + } + return _cachedServiceDescription; + } + + static FlogServiceProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + FlogServiceProxy p = new FlogServiceProxy.unbound(); + String name = serviceName ?? FlogService.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void createLogger(FlogLoggerInterfaceRequest logger, String label); + dynamic getLogDescriptions([Function responseFactory = null]); + void createReader(FlogReaderInterfaceRequest reader, int logId); +} + +abstract class FlogServiceInterface + implements bindings.MojoInterface<FlogService>, + FlogService { + factory FlogServiceInterface([FlogService impl]) => + new FlogServiceStub.unbound(impl); + factory FlogServiceInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [FlogService impl]) => + new FlogServiceStub.fromEndpoint(endpoint, impl); +} + +abstract class FlogServiceInterfaceRequest + implements bindings.MojoInterface<FlogService>, + FlogService { + factory FlogServiceInterfaceRequest() => + new FlogServiceProxy.unbound(); +} + +class _FlogServiceProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl<FlogService> { + _FlogServiceProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); + + _FlogServiceProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); + + _FlogServiceProxyControl.unbound() : super.unbound(); + + String get serviceName => FlogService.serviceName; + + void handleResponse(bindings.ServiceMessage message) { + switch (message.header.type) { + case _flogServiceMethodGetLogDescriptionsName: + var r = FlogServiceGetLogDescriptionsResponseParams.deserialize( + message.payload); + if (!message.header.hasRequestId) { + proxyError("Expected a message with a valid request Id."); + return; + } + Completer c = completerMap[message.header.requestId]; + if (c == null) { + proxyError( + "Message had unknown request Id: ${message.header.requestId}"); + return; + } + completerMap.remove(message.header.requestId); + if (c.isCompleted) { + proxyError("Response completer already completed"); + return; + } + c.complete(r); + break; + default: + proxyError("Unexpected message type: ${message.header.type}"); + close(immediate: true); + break; + } + } + + FlogService get impl => null; + set impl(FlogService _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override + String toString() { + var superString = super.toString(); + return "_FlogServiceProxyControl($superString)"; + } +} + +class FlogServiceProxy + extends bindings.Proxy<FlogService> + implements FlogService, + FlogServiceInterface, + FlogServiceInterfaceRequest { + FlogServiceProxy.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) + : super(new _FlogServiceProxyControl.fromEndpoint(endpoint)); + + FlogServiceProxy.fromHandle(core.MojoHandle handle) + : super(new _FlogServiceProxyControl.fromHandle(handle)); + + FlogServiceProxy.unbound() + : super(new _FlogServiceProxyControl.unbound()); + + static FlogServiceProxy newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For FlogServiceProxy")); + return new FlogServiceProxy.fromEndpoint(endpoint); + } + + + void createLogger(FlogLoggerInterfaceRequest logger, String label) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _FlogServiceCreateLoggerParams(); + params.logger = logger; + params.label = label; + ctrl.sendMessage(params, + _flogServiceMethodCreateLoggerName); + } + dynamic getLogDescriptions([Function responseFactory = null]) { + var params = new _FlogServiceGetLogDescriptionsParams(); + return ctrl.sendMessageWithRequestId( + params, + _flogServiceMethodGetLogDescriptionsName, + -1, + bindings.MessageHeader.kMessageExpectsResponse); + } + void createReader(FlogReaderInterfaceRequest reader, int logId) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _FlogServiceCreateReaderParams(); + params.reader = reader; + params.logId = logId; + ctrl.sendMessage(params, + _flogServiceMethodCreateReaderName); + } +} + +class _FlogServiceStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl<FlogService> { + FlogService _impl; + + _FlogServiceStubControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [FlogService impl]) + : super.fromEndpoint(endpoint, autoBegin: impl != null) { + _impl = impl; + } + + _FlogServiceStubControl.fromHandle( + core.MojoHandle handle, [FlogService impl]) + : super.fromHandle(handle, autoBegin: impl != null) { + _impl = impl; + } + + _FlogServiceStubControl.unbound([this._impl]) : super.unbound(); + + String get serviceName => FlogService.serviceName; + + + FlogServiceGetLogDescriptionsResponseParams _flogServiceGetLogDescriptionsResponseParamsFactory(List<FlogDescription> descriptions) { + var result = new FlogServiceGetLogDescriptionsResponseParams(); + result.descriptions = descriptions; + return result; + } + + dynamic handleMessage(bindings.ServiceMessage message) { + if (bindings.ControlMessageHandler.isControlMessage(message)) { + return bindings.ControlMessageHandler.handleMessage(this, + 0, + message); + } + if (_impl == null) { + throw new core.MojoApiError("$this has no implementation set"); + } + switch (message.header.type) { + case _flogServiceMethodCreateLoggerName: + var params = _FlogServiceCreateLoggerParams.deserialize( + message.payload); + _impl.createLogger(params.logger, params.label); + break; + case _flogServiceMethodGetLogDescriptionsName: + var response = _impl.getLogDescriptions(_flogServiceGetLogDescriptionsResponseParamsFactory); + if (response is Future) { + return response.then((response) { + if (response != null) { + return buildResponseWithId( + response, + _flogServiceMethodGetLogDescriptionsName, + message.header.requestId, + bindings.MessageHeader.kMessageIsResponse); + } + }); + } else if (response != null) { + return buildResponseWithId( + response, + _flogServiceMethodGetLogDescriptionsName, + message.header.requestId, + bindings.MessageHeader.kMessageIsResponse); + } + break; + case _flogServiceMethodCreateReaderName: + var params = _FlogServiceCreateReaderParams.deserialize( + message.payload); + _impl.createReader(params.reader, params.logId); + break; + default: + throw new bindings.MojoCodecError("Unexpected message name"); + break; + } + return null; + } + + FlogService get impl => _impl; + set impl(FlogService d) { + if (d == null) { + throw new core.MojoApiError("$this: Cannot set a null implementation"); + } + if (isBound && (_impl == null)) { + beginHandlingEvents(); + } + _impl = d; + } + + @override + void bind(core.MojoMessagePipeEndpoint endpoint) { + super.bind(endpoint); + if (!isOpen && (_impl != null)) { + beginHandlingEvents(); + } + } + + @override + String toString() { + var superString = super.toString(); + return "_FlogServiceStubControl($superString)"; + } + + int get version => 0; +} + +class FlogServiceStub + extends bindings.Stub<FlogService> + implements FlogService, + FlogServiceInterface, + FlogServiceInterfaceRequest { + FlogServiceStub.unbound([FlogService impl]) + : super(new _FlogServiceStubControl.unbound(impl)); + + FlogServiceStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [FlogService impl]) + : super(new _FlogServiceStubControl.fromEndpoint(endpoint, impl)); + + FlogServiceStub.fromHandle( + core.MojoHandle handle, [FlogService impl]) + : super(new _FlogServiceStubControl.fromHandle(handle, impl)); + + static FlogServiceStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For FlogServiceStub")); + return new FlogServiceStub.fromEndpoint(endpoint); + } + + + void createLogger(FlogLoggerInterfaceRequest logger, String label) { + return impl.createLogger(logger, label); + } + dynamic getLogDescriptions([Function responseFactory = null]) { + return impl.getLogDescriptions(responseFactory); + } + void createReader(FlogReaderInterfaceRequest reader, int logId) { + return impl.createReader(reader, logId); + } +} + +const int _flogLoggerMethodLogChannelCreationName = 0; +const int _flogLoggerMethodLogChannelMessageName = 1; +const int _flogLoggerMethodLogChannelDeletionName = 2; + +class _FlogLoggerServiceDescription implements service_describer.ServiceDescription { + dynamic getTopLevelInterface([Function responseFactory]) => + responseFactory(null); + + dynamic getTypeDefinition(String typeKey, [Function responseFactory]) => + responseFactory(null); + + dynamic getAllTypeDefinitions([Function responseFactory]) => + responseFactory(null); +} + +abstract class FlogLogger { + static const String serviceName = null; + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _FlogLoggerServiceDescription(); + } + return _cachedServiceDescription; + } + + static FlogLoggerProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + FlogLoggerProxy p = new FlogLoggerProxy.unbound(); + String name = serviceName ?? FlogLogger.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void logChannelCreation(int timeUs, int channelId, String typeName); + void logChannelMessage(int timeUs, int channelId, List<int> data); + void logChannelDeletion(int timeUs, int channelId); +} + +abstract class FlogLoggerInterface + implements bindings.MojoInterface<FlogLogger>, + FlogLogger { + factory FlogLoggerInterface([FlogLogger impl]) => + new FlogLoggerStub.unbound(impl); + factory FlogLoggerInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [FlogLogger impl]) => + new FlogLoggerStub.fromEndpoint(endpoint, impl); +} + +abstract class FlogLoggerInterfaceRequest + implements bindings.MojoInterface<FlogLogger>, + FlogLogger { + factory FlogLoggerInterfaceRequest() => + new FlogLoggerProxy.unbound(); +} + +class _FlogLoggerProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl<FlogLogger> { + _FlogLoggerProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); + + _FlogLoggerProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); + + _FlogLoggerProxyControl.unbound() : super.unbound(); + + String get serviceName => FlogLogger.serviceName; + + void handleResponse(bindings.ServiceMessage message) { + switch (message.header.type) { + default: + proxyError("Unexpected message type: ${message.header.type}"); + close(immediate: true); + break; + } + } + + FlogLogger get impl => null; + set impl(FlogLogger _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override + String toString() { + var superString = super.toString(); + return "_FlogLoggerProxyControl($superString)"; + } +} + +class FlogLoggerProxy + extends bindings.Proxy<FlogLogger> + implements FlogLogger, + FlogLoggerInterface, + FlogLoggerInterfaceRequest { + FlogLoggerProxy.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) + : super(new _FlogLoggerProxyControl.fromEndpoint(endpoint)); + + FlogLoggerProxy.fromHandle(core.MojoHandle handle) + : super(new _FlogLoggerProxyControl.fromHandle(handle)); + + FlogLoggerProxy.unbound() + : super(new _FlogLoggerProxyControl.unbound()); + + static FlogLoggerProxy newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For FlogLoggerProxy")); + return new FlogLoggerProxy.fromEndpoint(endpoint); + } + + + void logChannelCreation(int timeUs, int channelId, String typeName) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _FlogLoggerLogChannelCreationParams(); + params.timeUs = timeUs; + params.channelId = channelId; + params.typeName = typeName; + ctrl.sendMessage(params, + _flogLoggerMethodLogChannelCreationName); + } + void logChannelMessage(int timeUs, int channelId, List<int> data) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _FlogLoggerLogChannelMessageParams(); + params.timeUs = timeUs; + params.channelId = channelId; + params.data = data; + ctrl.sendMessage(params, + _flogLoggerMethodLogChannelMessageName); + } + void logChannelDeletion(int timeUs, int channelId) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _FlogLoggerLogChannelDeletionParams(); + params.timeUs = timeUs; + params.channelId = channelId; + ctrl.sendMessage(params, + _flogLoggerMethodLogChannelDeletionName); + } +} + +class _FlogLoggerStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl<FlogLogger> { + FlogLogger _impl; + + _FlogLoggerStubControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [FlogLogger impl]) + : super.fromEndpoint(endpoint, autoBegin: impl != null) { + _impl = impl; + } + + _FlogLoggerStubControl.fromHandle( + core.MojoHandle handle, [FlogLogger impl]) + : super.fromHandle(handle, autoBegin: impl != null) { + _impl = impl; + } + + _FlogLoggerStubControl.unbound([this._impl]) : super.unbound(); + + String get serviceName => FlogLogger.serviceName; + + + + dynamic handleMessage(bindings.ServiceMessage message) { + if (bindings.ControlMessageHandler.isControlMessage(message)) { + return bindings.ControlMessageHandler.handleMessage(this, + 0, + message); + } + if (_impl == null) { + throw new core.MojoApiError("$this has no implementation set"); + } + switch (message.header.type) { + case _flogLoggerMethodLogChannelCreationName: + var params = _FlogLoggerLogChannelCreationParams.deserialize( + message.payload); + _impl.logChannelCreation(params.timeUs, params.channelId, params.typeName); + break; + case _flogLoggerMethodLogChannelMessageName: + var params = _FlogLoggerLogChannelMessageParams.deserialize( + message.payload); + _impl.logChannelMessage(params.timeUs, params.channelId, params.data); + break; + case _flogLoggerMethodLogChannelDeletionName: + var params = _FlogLoggerLogChannelDeletionParams.deserialize( + message.payload); + _impl.logChannelDeletion(params.timeUs, params.channelId); + break; + default: + throw new bindings.MojoCodecError("Unexpected message name"); + break; + } + return null; + } + + FlogLogger get impl => _impl; + set impl(FlogLogger d) { + if (d == null) { + throw new core.MojoApiError("$this: Cannot set a null implementation"); + } + if (isBound && (_impl == null)) { + beginHandlingEvents(); + } + _impl = d; + } + + @override + void bind(core.MojoMessagePipeEndpoint endpoint) { + super.bind(endpoint); + if (!isOpen && (_impl != null)) { + beginHandlingEvents(); + } + } + + @override + String toString() { + var superString = super.toString(); + return "_FlogLoggerStubControl($superString)"; + } + + int get version => 0; +} + +class FlogLoggerStub + extends bindings.Stub<FlogLogger> + implements FlogLogger, + FlogLoggerInterface, + FlogLoggerInterfaceRequest { + FlogLoggerStub.unbound([FlogLogger impl]) + : super(new _FlogLoggerStubControl.unbound(impl)); + + FlogLoggerStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [FlogLogger impl]) + : super(new _FlogLoggerStubControl.fromEndpoint(endpoint, impl)); + + FlogLoggerStub.fromHandle( + core.MojoHandle handle, [FlogLogger impl]) + : super(new _FlogLoggerStubControl.fromHandle(handle, impl)); + + static FlogLoggerStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For FlogLoggerStub")); + return new FlogLoggerStub.fromEndpoint(endpoint); + } + + + void logChannelCreation(int timeUs, int channelId, String typeName) { + return impl.logChannelCreation(timeUs, channelId, typeName); + } + void logChannelMessage(int timeUs, int channelId, List<int> data) { + return impl.logChannelMessage(timeUs, channelId, data); + } + void logChannelDeletion(int timeUs, int channelId) { + return impl.logChannelDeletion(timeUs, channelId); + } +} + +const int _flogReaderMethodGetEntriesName = 0; + +class _FlogReaderServiceDescription implements service_describer.ServiceDescription { + dynamic getTopLevelInterface([Function responseFactory]) => + responseFactory(null); + + dynamic getTypeDefinition(String typeKey, [Function responseFactory]) => + responseFactory(null); + + dynamic getAllTypeDefinitions([Function responseFactory]) => + responseFactory(null); +} + +abstract class FlogReader { + static const String serviceName = null; + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _FlogReaderServiceDescription(); + } + return _cachedServiceDescription; + } + + static FlogReaderProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + FlogReaderProxy p = new FlogReaderProxy.unbound(); + String name = serviceName ?? FlogReader.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + dynamic getEntries(int startIndex,int maxCount,[Function responseFactory = null]); +} + +abstract class FlogReaderInterface + implements bindings.MojoInterface<FlogReader>, + FlogReader { + factory FlogReaderInterface([FlogReader impl]) => + new FlogReaderStub.unbound(impl); + factory FlogReaderInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [FlogReader impl]) => + new FlogReaderStub.fromEndpoint(endpoint, impl); +} + +abstract class FlogReaderInterfaceRequest + implements bindings.MojoInterface<FlogReader>, + FlogReader { + factory FlogReaderInterfaceRequest() => + new FlogReaderProxy.unbound(); +} + +class _FlogReaderProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl<FlogReader> { + _FlogReaderProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); + + _FlogReaderProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); + + _FlogReaderProxyControl.unbound() : super.unbound(); + + String get serviceName => FlogReader.serviceName; + + void handleResponse(bindings.ServiceMessage message) { + switch (message.header.type) { + case _flogReaderMethodGetEntriesName: + var r = FlogReaderGetEntriesResponseParams.deserialize( + message.payload); + if (!message.header.hasRequestId) { + proxyError("Expected a message with a valid request Id."); + return; + } + Completer c = completerMap[message.header.requestId]; + if (c == null) { + proxyError( + "Message had unknown request Id: ${message.header.requestId}"); + return; + } + completerMap.remove(message.header.requestId); + if (c.isCompleted) { + proxyError("Response completer already completed"); + return; + } + c.complete(r); + break; + default: + proxyError("Unexpected message type: ${message.header.type}"); + close(immediate: true); + break; + } + } + + FlogReader get impl => null; + set impl(FlogReader _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override + String toString() { + var superString = super.toString(); + return "_FlogReaderProxyControl($superString)"; + } +} + +class FlogReaderProxy + extends bindings.Proxy<FlogReader> + implements FlogReader, + FlogReaderInterface, + FlogReaderInterfaceRequest { + FlogReaderProxy.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) + : super(new _FlogReaderProxyControl.fromEndpoint(endpoint)); + + FlogReaderProxy.fromHandle(core.MojoHandle handle) + : super(new _FlogReaderProxyControl.fromHandle(handle)); + + FlogReaderProxy.unbound() + : super(new _FlogReaderProxyControl.unbound()); + + static FlogReaderProxy newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For FlogReaderProxy")); + return new FlogReaderProxy.fromEndpoint(endpoint); + } + + + dynamic getEntries(int startIndex,int maxCount,[Function responseFactory = null]) { + var params = new _FlogReaderGetEntriesParams(); + params.startIndex = startIndex; + params.maxCount = maxCount; + return ctrl.sendMessageWithRequestId( + params, + _flogReaderMethodGetEntriesName, + -1, + bindings.MessageHeader.kMessageExpectsResponse); + } +} + +class _FlogReaderStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl<FlogReader> { + FlogReader _impl; + + _FlogReaderStubControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [FlogReader impl]) + : super.fromEndpoint(endpoint, autoBegin: impl != null) { + _impl = impl; + } + + _FlogReaderStubControl.fromHandle( + core.MojoHandle handle, [FlogReader impl]) + : super.fromHandle(handle, autoBegin: impl != null) { + _impl = impl; + } + + _FlogReaderStubControl.unbound([this._impl]) : super.unbound(); + + String get serviceName => FlogReader.serviceName; + + + FlogReaderGetEntriesResponseParams _flogReaderGetEntriesResponseParamsFactory(List<FlogEntry> entries, int entryCount, bool open) { + var result = new FlogReaderGetEntriesResponseParams(); + result.entries = entries; + result.entryCount = entryCount; + result.open = open; + return result; + } + + dynamic handleMessage(bindings.ServiceMessage message) { + if (bindings.ControlMessageHandler.isControlMessage(message)) { + return bindings.ControlMessageHandler.handleMessage(this, + 0, + message); + } + if (_impl == null) { + throw new core.MojoApiError("$this has no implementation set"); + } + switch (message.header.type) { + case _flogReaderMethodGetEntriesName: + var params = _FlogReaderGetEntriesParams.deserialize( + message.payload); + var response = _impl.getEntries(params.startIndex,params.maxCount,_flogReaderGetEntriesResponseParamsFactory); + if (response is Future) { + return response.then((response) { + if (response != null) { + return buildResponseWithId( + response, + _flogReaderMethodGetEntriesName, + message.header.requestId, + bindings.MessageHeader.kMessageIsResponse); + } + }); + } else if (response != null) { + return buildResponseWithId( + response, + _flogReaderMethodGetEntriesName, + message.header.requestId, + bindings.MessageHeader.kMessageIsResponse); + } + break; + default: + throw new bindings.MojoCodecError("Unexpected message name"); + break; + } + return null; + } + + FlogReader get impl => _impl; + set impl(FlogReader d) { + if (d == null) { + throw new core.MojoApiError("$this: Cannot set a null implementation"); + } + if (isBound && (_impl == null)) { + beginHandlingEvents(); + } + _impl = d; + } + + @override + void bind(core.MojoMessagePipeEndpoint endpoint) { + super.bind(endpoint); + if (!isOpen && (_impl != null)) { + beginHandlingEvents(); + } + } + + @override + String toString() { + var superString = super.toString(); + return "_FlogReaderStubControl($superString)"; + } + + int get version => 0; +} + +class FlogReaderStub + extends bindings.Stub<FlogReader> + implements FlogReader, + FlogReaderInterface, + FlogReaderInterfaceRequest { + FlogReaderStub.unbound([FlogReader impl]) + : super(new _FlogReaderStubControl.unbound(impl)); + + FlogReaderStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [FlogReader impl]) + : super(new _FlogReaderStubControl.fromEndpoint(endpoint, impl)); + + FlogReaderStub.fromHandle( + core.MojoHandle handle, [FlogReader impl]) + : super(new _FlogReaderStubControl.fromHandle(handle, impl)); + + static FlogReaderStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For FlogReaderStub")); + return new FlogReaderStub.fromEndpoint(endpoint); + } + + + dynamic getEntries(int startIndex,int maxCount,[Function responseFactory = null]) { + return impl.getEntries(startIndex,maxCount,responseFactory); + } +} + + +
diff --git a/mojo/services/flog/cpp/BUILD.gn b/mojo/services/flog/cpp/BUILD.gn new file mode 100644 index 0000000..dafae11 --- /dev/null +++ b/mojo/services/flog/cpp/BUILD.gn
@@ -0,0 +1,20 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/module_args/mojo.gni") +import("$mojo_sdk_root/mojo/public/mojo_sdk.gni") + +mojo_sdk_source_set("cpp") { + sources = [ + "flog.cc", + "flog.h", + ] + + deps = [ + "$mojo_sdk_root/mojo/public/cpp/application", + "$mojo_sdk_root/mojo/public/cpp/bindings", + "$mojo_sdk_root/mojo/public/cpp/environment", + "$mojo_sdk_root/mojo/services/flog/interfaces", + ] +}
diff --git a/mojo/services/flog/cpp/flog.cc b/mojo/services/flog/cpp/flog.cc new file mode 100644 index 0000000..3493682 --- /dev/null +++ b/mojo/services/flog/cpp/flog.cc
@@ -0,0 +1,37 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/services/flog/cpp/flog.h" + +namespace mojo { +namespace flog { + +// static +std::atomic_ulong Flog::last_allocated_channel_id_; + +// static +FlogLoggerPtr Flog::logger_; + +FlogChannel::FlogChannel(const char* channel_type_name) + : id_(Flog::AllocateChannelId()) { + Flog::LogChannelCreation(id_, channel_type_name); +} + +FlogChannel::~FlogChannel() { + Flog::LogChannelDeletion(id_); +} + +bool FlogChannel::Accept(Message* message) { + Flog::LogChannelMessage(id_, message); + return true; +} + +bool FlogChannel::AcceptWithResponder(Message* message, + MessageReceiver* responder) { + MOJO_DCHECK(false) << "Flog doesn't support messages with responses"; + abort(); +} + +} // namespace flog +} // namespace mojo
diff --git a/mojo/services/flog/cpp/flog.h b/mojo/services/flog/cpp/flog.h new file mode 100644 index 0000000..5badda1 --- /dev/null +++ b/mojo/services/flog/cpp/flog.h
@@ -0,0 +1,197 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_SERVICES_FLOG_CPP_FLOG_H_ +#define MOJO_SERVICES_FLOG_CPP_FLOG_H_ + +#include <atomic> +#include <memory> + +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/connect.h" +#include "mojo/public/cpp/bindings/array.h" +#include "mojo/public/cpp/bindings/message.h" +#include "mojo/public/cpp/environment/logging.h" +#include "mojo/public/cpp/system/time.h" +#include "mojo/services/flog/interfaces/flog.mojom.h" + +namespace mojo { +namespace flog { + +// +// FORMATTED LOGGING +// +// The Flog class and associated macros provide a means of logging 'formatted' +// log messages serialized by Mojo. Flog uses an instance of FlogLogger to +// log events to the FlogService. Messages pulled from the FlogService can be +// deserialized using Mojo on behalf of log visualization and analysis tools. +// +// Message logging is performed using a 'channel', which is bound to a Mojo +// proxy for a particular interface. Mojo interfaces used for this purpose must +// be request-only, meaning the constituent methods must not have responses. +// +// Assume that we've defined the following interface: +// +// [ServiceName="my_namespace::MyFlogChannelInterface"] +// interface MyFlogChannelInterface { +// Thing1(int64 a, int32 b); +// Thing2(string c); +// }; +// +// Note that the ServiceName annotation is required. +// +// A channel instance may be defined, typically as a member of a class, as +// follows: +// +// FLOG_CHANNEL(MyFlogChannelInterface, my_flog_channel_instance_); +// +// If NDEBUG is defined, this compiles to nothing. Otherwise, it declares and +// initializes my_flog_channel_instance, which can be used via the FLOG macro: +// +// FLOG(my_flog_channel_instance_, Thing1(1234, 5678)); +// FLOG(my_flog_channel_instance_, Thing2("To the lifeboats!")); +// +// These invocations compile to nothing if NDEBUG is defined. Otherwise, they +// log messages to the channel represented by my_flog_channel_instance. +// +// FLOG_CHANNEL_DECL produces only a declaration for cases in which a channel +// must be declared but not defined (e.g. as a static class member). +// +// Logging to a channel does nothing unless the Flog class has been initialized +// with a call to Flog::Initialize. Flog::Initialize provides a FlogLogger +// implementation to be used for logging. Typically, this implementation would +// be acquired from the FlogService using CreateLogger. +// + +#if defined(NDEBUG) + +#define FLOG_INITIALIZE(app_or_logger, label) ((void)0) +#define FLOG_DESTROY() ((void)0) +#define FLOG_CHANNEL(channel_type, channel_name) +#define FLOG_CHANNEL_DECL(channel_type, channel_name) +#define FLOG(channel_name, call) ((void)0) +#define FLOG_ID(channel_name) 0 + +#else + +#define FLOG_INITIALIZE(app_or_logger, label) \ + mojo::flog::Flog::Initialize(app_or_logger, label) + +#define FLOG_DESTROY() mojo::flog::Flog::Destroy() + +#define FLOG_CHANNEL(channel_type, channel_name) \ + std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name = \ + mojo::flog::FlogProxy<channel_type>::Create() + +#define FLOG_CHANNEL_DECL(channel_type, channel_name) \ + std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name + +#define FLOG(channel_name, call) channel_name->call + +#define FLOG_ID(channel_name) channel_name->channel()->id() + +#endif + +// Thread-safe logger for all channels in a given process. +class Flog { + public: + static void Initialize(ApplicationImpl* app, const std::string& label) { + MOJO_DCHECK(!logger_); + FlogServicePtr flog_service; + FlogLoggerPtr flog_logger; + ConnectToService(app->shell(), "mojo:flog", GetProxy(&flog_service)); + flog_service->CreateLogger(GetProxy(&flog_logger), label); + logger_ = flog_logger.Pass(); + } + + // Sets the flog logger singleton. + static void Initialize(FlogLoggerPtr flog_logger) { + MOJO_DCHECK(!logger_); + logger_ = flog_logger.Pass(); + } + + // Deletes the flog logger singleton. + static void Destroy() { + MOJO_DCHECK(logger_); + logger_.reset(); + } + + // Allocates a unique id for a new channel. Never returns 0. + static uint32_t AllocateChannelId() { return ++last_allocated_channel_id_; } + + // Logs the creation of a channel. + static void LogChannelCreation(uint32_t channel_id, + const char* channel_type_name) { + if (!logger_) { + return; + } + + logger_->LogChannelCreation(GetTimeTicksNow(), channel_id, + channel_type_name); + } + + // Logs a channel message. + static void LogChannelMessage(uint32_t channel_id, Message* message) { + if (!logger_) { + return; + } + + Array<uint8_t> array = Array<uint8_t>::New(message->data_num_bytes()); + memcpy(array.data(), message->data(), message->data_num_bytes()); + logger_->LogChannelMessage(GetTimeTicksNow(), channel_id, array.Pass()); + } + + // Logs the deletion of a channel. + static void LogChannelDeletion(uint32_t channel_id) { + if (!logger_) { + return; + } + + logger_->LogChannelDeletion(GetTimeTicksNow(), channel_id); + } + + private: + static std::atomic_ulong last_allocated_channel_id_; + static FlogLoggerPtr logger_; +}; + +// Channel backing a FlogProxy. +class FlogChannel : public MessageReceiverWithResponder { + public: + FlogChannel(const char* channel_type_name); + + ~FlogChannel() override; + + // Returns the channel id. + uint32_t id() const { return id_; } + + // MessageReceiverWithResponder implementation. + bool Accept(Message* message) override; + + bool AcceptWithResponder(Message* message, + MessageReceiver* responder) override; + + private: + uint32_t id_ = 0; +}; + +template <typename T> +class FlogProxy : public T::Proxy_ { + public: + static std::unique_ptr<FlogProxy<T>> Create() { + return std::unique_ptr<FlogProxy<T>>(new FlogProxy<T>()); + } + + FlogChannel* channel() { + return reinterpret_cast<FlogChannel*>(this->receiver_); + } + + private: + explicit FlogProxy() : T::Proxy_(new FlogChannel(T::Name_)) {} +}; + +} // namespace flog +} // namespace mojo + +#endif // MOJO_SERVICES_FLOG_CPP_FLOG_H_
diff --git a/mojo/services/flog/interfaces/BUILD.gn b/mojo/services/flog/interfaces/BUILD.gn new file mode 100644 index 0000000..623c356 --- /dev/null +++ b/mojo/services/flog/interfaces/BUILD.gn
@@ -0,0 +1,12 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/module_args/mojo.gni") +import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "flog.mojom", + ] +}
diff --git a/mojo/services/flog/interfaces/flog.mojom b/mojo/services/flog/interfaces/flog.mojom new file mode 100644 index 0000000..0c6f171 --- /dev/null +++ b/mojo/services/flog/interfaces/flog.mojom
@@ -0,0 +1,75 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[DartPackage="mojo_services"] +module mojo.flog; + +// TODO(dalesat): Move out of media to somewhere more generic. + +// Exposed by the log service to enable creation and consumption of logs. +[ServiceName="mojo::flog::FlogService"] +interface FlogService { + // Creates a new logger. + CreateLogger(FlogLogger& logger, string label); + + // Gets the descriptions of all logs. + GetLogDescriptions() => (array<FlogDescription> descriptions); + + // Gets a reader for the specified log. + CreateReader(FlogReader& reader, uint32 log_id); +}; + +// A logger that logs messages regarding multiple channels. +interface FlogLogger { + // Logs the creation of a channel. + LogChannelCreation(int64 time_us, uint32 channel_id, string type_name); + + // Logs a message sent to an existing channel. + LogChannelMessage(int64 time_us, uint32 channel_id, array<uint8> data); + + // Logs the deletion of a channel. + LogChannelDeletion(int64 time_us, uint32 channel_id); +}; + +// A reader that reads messages from one or more logs. +interface FlogReader { + // Gets entries from the log starting and the specified index (entries are + // indexed starting at 0). If the log is open, the callback will be called + // when max_count entries are avaiable starting at start_index. If the log + // is closed, the callback will be called immediately with as many entries + // as are available starting at start_index and not exceeding max_count + // entries. entry_count and open refer to the entire log at the time the + // callback occurred. + GetEntries(uint32 start_index, uint32 max_count) => + (array<FlogEntry> entries, uint32 entry_count, bool open); +}; + +struct FlogDescription { + string label; + uint32 log_id; + uint32 entry_count; + int64 start_time_us; + int64 stop_time_us; + bool open; +}; + +struct FlogEntry { + int64 time_us; + uint32 log_id; + uint32 channel_id; + FlogEntryDetails? details; +}; + +union FlogEntryDetails { + FlogChannelCreationEntryDetails channel_creation; + FlogChannelMessageEntryDetails channel_message; +}; + +struct FlogChannelCreationEntryDetails { + string type_name; +}; + +struct FlogChannelMessageEntryDetails { + array<uint8> data; +};
diff --git a/mojo/services/mojo_services.gni b/mojo/services/mojo_services.gni index dc6e0ec..cb2b814 100644 --- a/mojo/services/mojo_services.gni +++ b/mojo/services/mojo_services.gni
@@ -18,6 +18,7 @@ "//mojo/services/content_handler/interfaces", "//mojo/services/device_info/interfaces", "//mojo/services/files/interfaces", + "//mojo/services/flog/interfaces", "//mojo/services/geometry/interfaces", "//mojo/services/gfx/composition/interfaces", "//mojo/services/gpu/interfaces",