1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
# Copyright (C) 2016 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'rbconfig'
module Mongo
class Cluster
# Application metadata that is sent to the server in an ismaster command,
# when a new connection is established.
#
# @api private
#
# @since 2.4.0
class AppMetadata
extend Forwardable
# The max application metadata document byte size.
#
# @since 2.4.0
MAX_DOCUMENT_SIZE = 512.freeze
# The max application name byte size.
#
# @ since 2.4.0
MAX_APP_NAME_SIZE = 128.freeze
# The driver name.
#
# @ since 2.4.0
DRIVER_NAME = 'mongo-ruby-driver'
# Instantiate the new AppMetadata object.
#
# @api private
#
# @example Instantiate the app metadata.
# Mongo::Cluster.AppMetadata.new(cluster)
#
# @param [ Mongo::Cluster ] cluster The cluster.
#
# @since 2.4.0
def initialize(cluster)
@app_name = cluster.options[:app_name]
@platform = cluster.options[:platform]
@compressors = cluster.options[:compressors] || []
end
# Get the bytes of the ismaster message including this metadata.
#
# @api private
#
# @example Get the ismaster message bytes.
# metadata.ismaster_bytes
#
# @return [ String ] The raw bytes.
#
# @since 2.4.0
def ismaster_bytes
@ismaster_bytes ||= validate! && serialize.to_s
end
private
def validate!
if @app_name && @app_name.bytesize > MAX_APP_NAME_SIZE
raise Error::InvalidApplicationName.new(@app_name, MAX_APP_NAME_SIZE)
end
true
end
def full_client_document
BSON::Document.new.tap do |doc|
doc[:application] = { name: @app_name } if @app_name
doc[:driver] = driver_doc
doc[:os] = os_doc
doc[:platform] = platform
end
end
def serialize
Protocol::Query.new(Database::ADMIN, Database::COMMAND, document, :limit => -1).serialize
end
def document
client_document = full_client_document
while client_document.to_bson.to_s.size > MAX_DOCUMENT_SIZE do
if client_document[:os][:name] || client_document[:os][:architecture]
client_document[:os].delete(:name)
client_document[:os].delete(:architecture)
elsif client_document[:platform]
client_document.delete(:platform)
else
client_document = nil
end
end
document = Server::Monitor::Connection::ISMASTER
document = document.merge(compression: @compressors)
document[:client] = client_document
document
end
def driver_doc
{
name: DRIVER_NAME,
version: Mongo::VERSION
}
end
def os_doc
{
type: type,
name: name,
architecture: architecture
}
end
def type
(RbConfig::CONFIG && RbConfig::CONFIG['host_os']) ?
RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase : 'unknown'
end
def name
RbConfig::CONFIG['host_os']
end
def architecture
RbConfig::CONFIG['target_cpu']
end
def platform
[
@platform,
RUBY_VERSION,
RUBY_PLATFORM,
RbConfig::CONFIG['build']
].compact.join(', ')
end
end
end
end
|