~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to proxy/logging/LogHost.cc

  • Committer: Bazaar Package Importer
  • Author(s): Arno Toell
  • Date: 2011-01-13 11:49:18 UTC
  • Revision ID: james.westby@ubuntu.com-20110113114918-vu422h8dknrgkj15
Tags: upstream-2.1.5-unstable
ImportĀ upstreamĀ versionĀ 2.1.5-unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  A brief file description
 
4
 
 
5
  @section license License
 
6
 
 
7
  Licensed to the Apache Software Foundation (ASF) under one
 
8
  or more contributor license agreements.  See the NOTICE file
 
9
  distributed with this work for additional information
 
10
  regarding copyright ownership.  The ASF licenses this file
 
11
  to you under the Apache License, Version 2.0 (the
 
12
  "License"); you may not use this file except in compliance
 
13
  with the License.  You may obtain a copy of the License at
 
14
 
 
15
      http://www.apache.org/licenses/LICENSE-2.0
 
16
 
 
17
  Unless required by applicable law or agreed to in writing, software
 
18
  distributed under the License is distributed on an "AS IS" BASIS,
 
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
20
  See the License for the specific language governing permissions and
 
21
  limitations under the License.
 
22
 */
 
23
 
 
24
/***************************************************************************
 
25
 LogHost.cc
 
26
 
 
27
 
 
28
 ***************************************************************************/
 
29
#include "libts.h"
 
30
 
 
31
#include "Resource.h"
 
32
#include "Error.h"
 
33
 
 
34
#include "LogUtils.h"
 
35
#include "LogSock.h"
 
36
#include "LogField.h"
 
37
#include "LogFile.h"
 
38
#include "LogFormat.h"
 
39
#include "LogBuffer.h"
 
40
#include "LogHost.h"
 
41
#include "LogObject.h"
 
42
#include "LogConfig.h"
 
43
#include "Log.h"
 
44
 
 
45
#if defined(IOCORE_LOG_COLLATION)
 
46
#include "LogCollationClientSM.h"
 
47
#endif
 
48
 
 
49
#define PING    true
 
50
#define NOPING  false
 
51
 
 
52
/*-------------------------------------------------------------------------
 
53
  LogHost
 
54
  -------------------------------------------------------------------------*/
 
55
 
 
56
LogHost::LogHost(char *object_filename, uint64_t object_signature)
 
57
  : m_object_filename(xstrdup(object_filename))
 
58
  , m_object_signature(object_signature)
 
59
  , m_ip(0)
 
60
  , m_ipstr(NULL)
 
61
  , m_name(NULL)
 
62
  , m_port(0)
 
63
  , m_sock(NULL)
 
64
  , m_sock_fd(-1)
 
65
  , m_connected(false)
 
66
  , m_orphan_file(NULL)
 
67
#if defined (IOCORE_LOG_COLLATION)
 
68
  , m_log_collation_client_sm(NULL)
 
69
#endif
 
70
{
 
71
}
 
72
 
 
73
LogHost::LogHost(const LogHost & rhs)
 
74
  : m_object_filename(xstrdup(rhs.m_object_filename))
 
75
  , m_object_signature(rhs.m_object_signature)
 
76
  , m_ip(rhs.m_ip)
 
77
  , m_ipstr(xstrdup(rhs.m_ipstr))
 
78
  , m_name(xstrdup(rhs.m_name))
 
79
  , m_port(rhs.m_port)
 
80
  , m_sock(NULL)
 
81
  , m_sock_fd(-1)
 
82
  , m_connected(false)
 
83
  , m_orphan_file(NULL)
 
84
#if defined (IOCORE_LOG_COLLATION)
 
85
  , m_log_collation_client_sm(NULL)
 
86
#endif
 
87
{
 
88
  create_orphan_LogFile_object();
 
89
}
 
90
 
 
91
LogHost::~LogHost()
 
92
{
 
93
  clear();
 
94
  xfree(m_object_filename);
 
95
}
 
96
 
 
97
//
 
98
// There are 3 ways to establish a LogHost:
 
99
// - by "hostname:port" or IP:port", where IP is a string of the
 
100
//   form "xxx.xxx.xxx.xxx".
 
101
// - by specifying a hostname and a port (as separate arguments).
 
102
// - by specifying an ip and a port (as separate arguments).
 
103
//
 
104
 
 
105
int
 
106
LogHost::set_name_port(char *hostname, unsigned int pt)
 
107
{
 
108
  if (!hostname || hostname[0] == 0) {
 
109
    Note("Cannot establish LogHost with NULL hostname");
 
110
    return 1;
 
111
  }
 
112
 
 
113
  clear();                      // remove all previous state for this LogHost
 
114
 
 
115
  m_ip = 0;                     // make sure ip is 0 for iocore
 
116
#if !defined(IOCORE_LOG_COLLATION)
 
117
  m_ip = LogUtils::ip_from_host(hostname);
 
118
  m_ipstr = (char *) xmalloc(32);
 
119
  LogUtils::ip_to_str(m_ip, m_ipstr, 32);
 
120
#endif
 
121
  m_name = xstrdup(hostname);
 
122
  m_port = pt;
 
123
 
 
124
  Debug("log-host", "LogHost established as %s:%u", name(), port());
 
125
 
 
126
  create_orphan_LogFile_object();
 
127
  return 0;
 
128
}
 
129
 
 
130
int
 
131
LogHost::set_ipstr_port(char *ipstr, unsigned int pt)
 
132
{
 
133
  if (!ipstr || ipstr[0] == 0) {
 
134
    Note("Cannot establish LogHost with NULL ipstr");
 
135
    return 1;
 
136
  }
 
137
 
 
138
  clear();                      // remove all previous state for this LogHost
 
139
 
 
140
  m_ip = htonl(LogUtils::str_to_ip(ipstr));
 
141
  m_ipstr = xstrdup(ipstr);
 
142
  m_name = xstrdup(ipstr);
 
143
  m_port = pt;
 
144
 
 
145
  Debug("log-host", "LogHost established as %s:%u", name(), port());
 
146
 
 
147
  create_orphan_LogFile_object();
 
148
  return 0;
 
149
}
 
150
 
 
151
int
 
152
LogHost::set_name_or_ipstr(char *name_or_ip)
 
153
{
 
154
  int retVal = 1;
 
155
 
 
156
  if (name_or_ip && name_or_ip[0] != 0) {
 
157
    SimpleTokenizer tok(name_or_ip, ':');
 
158
    char *n = tok.getNext();
 
159
    if (n) {
 
160
      char *p = tok.getNext();
 
161
      unsigned int port = (p ? (unsigned int) atoi(p) : Log::config->collation_port);
 
162
 
 
163
      if (LogUtils::valid_ipstr_format(n)) {
 
164
        retVal = set_ipstr_port(n, port);
 
165
      } else {
 
166
        retVal = set_name_port(n, port);
 
167
      }
 
168
    }
 
169
  }
 
170
  return retVal;
 
171
}
 
172
 
 
173
bool LogHost::connected(bool ping)
 
174
{
 
175
  if (m_connected && m_sock && m_sock_fd >= 0) {
 
176
    if (m_sock->is_connected(m_sock_fd, ping)) {
 
177
      return true;
 
178
    }
 
179
  }
 
180
  return false;
 
181
}
 
182
 
 
183
bool LogHost::connect()
 
184
{
 
185
  if (!m_ip) {
 
186
    Note("Cannot connect to LogHost; host IP has not been established");
 
187
    return false;
 
188
  }
 
189
 
 
190
  if (connected(PING)) {
 
191
    return true;
 
192
  }
 
193
 
 
194
  Debug("log-host", "Connecting to LogHost %s:%u", name(), port());
 
195
 
 
196
  disconnect();                 // make sure connection members are initialized
 
197
 
 
198
  if (m_sock == NULL) {
 
199
    m_sock = NEW(new LogSock());
 
200
    ink_assert(m_sock != NULL);
 
201
  }
 
202
  m_sock_fd = m_sock->connect(m_ip, m_port);
 
203
  if (m_sock_fd < 0) {
 
204
    Note("Connection to LogHost %s:%u failed", name(), port());
 
205
    return false;
 
206
  }
 
207
  m_connected = true;
 
208
 
 
209
  if (!authenticated()) {
 
210
    Note("Authentication to LogHost %s:%u failed", name(), port());
 
211
    disconnect();
 
212
    return false;
 
213
  }
 
214
 
 
215
  return true;
 
216
}
 
217
 
 
218
void
 
219
LogHost::disconnect()
 
220
{
 
221
  if (m_sock && m_sock_fd >= 0) {
 
222
    m_sock->close(m_sock_fd);
 
223
    m_sock_fd = -1;
 
224
  }
 
225
  m_connected = false;
 
226
}
 
227
 
 
228
int
 
229
LogHost::write(LogBuffer * lb, size_t * to_disk, size_t * to_net, size_t * to_pipe)
 
230
{
 
231
  NOWARN_UNUSED(to_pipe);
 
232
  if (lb == NULL) {
 
233
    Note("Cannot write LogBuffer to LogHost %s; LogBuffer is NULL", name());
 
234
    return -1;
 
235
  }
 
236
  LogBufferHeader *buffer_header = lb->header();
 
237
  if (buffer_header == NULL) {
 
238
    Note("Cannot write LogBuffer to LogHost %s; LogBufferHeader is NULL", name());
 
239
    return -1;
 
240
  }
 
241
  if (buffer_header->entry_count == 0) {
 
242
    // no bytes to write
 
243
    return 0;
 
244
  }
 
245
#if !defined(IOCORE_LOG_COLLATION)
 
246
 
 
247
  // make sure we're connected & authenticated
 
248
 
 
249
  if (!connected(NOPING)) {
 
250
    if (!connect()) {
 
251
      Note("Cannot write LogBuffer to LogHost %s; not connected", name());
 
252
      return orphan_write(lb);
 
253
    }
 
254
  }
 
255
  // try sending the logbuffer
 
256
 
 
257
  int bytes_to_send, bytes_sent;
 
258
  bytes_to_send = buffer_header->byte_count;
 
259
  lb->convert_to_network_order();
 
260
  bytes_sent = m_sock->write(m_sock_fd, buffer_header, bytes_to_send);
 
261
  if (bytes_to_send != bytes_sent) {
 
262
    Note("Bad write to LogHost %s; bad send count %d/%d", name(), bytes_sent, bytes_to_send);
 
263
    disconnect();
 
264
    lb->convert_to_host_order();
 
265
    return orphan_write(lb);
 
266
  }
 
267
 
 
268
  Debug("log-host", "%d bytes sent to LogHost %s:%u", bytes_sent, name(), port());
 
269
  // BUGBUG:: fix this, Log Collation should work on NT as well
 
270
  SUM_DYN_STAT(log_stat_bytes_sent_to_network_stat, bytes_sent);
 
271
  return bytes_sent;
 
272
 
 
273
#else // !defined(IOCORE_LOG_COLLATION)
 
274
 
 
275
  // make a copy of our log_buffer
 
276
  int buffer_header_size = buffer_header->byte_count;
 
277
  LogBufferHeader *buffer_header_copy = (LogBufferHeader *) NEW(new char[buffer_header_size]);
 
278
  ink_assert(buffer_header_copy != NULL);
 
279
 
 
280
  memcpy(buffer_header_copy, buffer_header, buffer_header_size);
 
281
  LogBuffer *lb_copy = NEW(new LogBuffer(lb->get_owner(),
 
282
                                         buffer_header_copy));
 
283
  ink_assert(lb_copy != NULL);
 
284
 
 
285
  // create a new collation client if necessary
 
286
  if (m_log_collation_client_sm == NULL) {
 
287
    m_log_collation_client_sm = NEW(new LogCollationClientSM(this));
 
288
    ink_assert(m_log_collation_client_sm != NULL);
 
289
  }
 
290
  // send log_buffer; orphan if necessary
 
291
  int bytes_sent = m_log_collation_client_sm->send(lb_copy);
 
292
  if (bytes_sent <= 0) {
 
293
#ifndef TS_MICRO
 
294
    bytes_sent = orphan_write_and_delete(lb_copy, to_disk);
 
295
#if defined(LOG_BUFFER_TRACKING)
 
296
    Debug("log-buftrak", "[%d]LogHost::write - orphan write complete", lb_copy->header()->id);
 
297
#endif // defined(LOG_BUFFER_TRACKING)
 
298
#else
 
299
    Note("Starting dropping log buffer due to overloading");
 
300
    delete lb_copy;
 
301
    lb_copy = 0;
 
302
#endif // TS_MICRO
 
303
  } else {
 
304
    if (to_net) {
 
305
      *to_net += bytes_sent;
 
306
    }
 
307
  }
 
308
 
 
309
  return bytes_sent;
 
310
 
 
311
#endif // !defined(IOCORE_LOG_COLLATION)
 
312
}
 
313
 
 
314
void
 
315
LogHost::create_orphan_LogFile_object()
 
316
{
 
317
  delete m_orphan_file;
 
318
 
 
319
  const char *orphan_ext = "orphan";
 
320
  unsigned name_len = (unsigned) (strlen(m_object_filename) + strlen(name()) + strlen(orphan_ext) + 16);
 
321
  char *name_buf = (char *) xmalloc(name_len);
 
322
  ink_assert(name_buf != NULL);
 
323
  // NT: replace ':'s with '-'s.  This change is necessary because
 
324
  // NT doesn't like filenames with ':'s in them.  ^_^
 
325
  snprintf(name_buf, name_len, "%s%s%s-%u.%s",
 
326
               m_object_filename, LOGFILE_SEPARATOR_STRING, name(), port(), orphan_ext);
 
327
 
 
328
  // should check for conflicts with orphan filename
 
329
  //
 
330
  m_orphan_file = NEW(new LogFile(name_buf, NULL, ASCII_LOG, m_object_signature));
 
331
  ink_assert(m_orphan_file != NULL);
 
332
  xfree(name_buf);
 
333
}
 
334
 
 
335
#ifndef TS_MICRO
 
336
int
 
337
LogHost::orphan_write(LogBuffer * lb, size_t * to_file)
 
338
{
 
339
  if (!Log::config->logging_space_exhausted) {
 
340
    Debug("log-host", "Sending LogBuffer to orphan file %s", m_orphan_file->get_name());
 
341
    return m_orphan_file->write(lb, to_file);
 
342
  } else {
 
343
    return 0;                   // nothing written
 
344
  }
 
345
}
 
346
 
 
347
int
 
348
LogHost::orphan_write_and_delete(LogBuffer * lb, size_t * to_disk)
 
349
{
 
350
  int bytes = orphan_write(lb, to_disk);
 
351
  // done with the buffer, delete it
 
352
  delete lb;
 
353
  lb = 0;
 
354
  return bytes;
 
355
}
 
356
#endif // TS_MICRO
 
357
 
 
358
void
 
359
LogHost::display(FILE * fd)
 
360
{
 
361
  fprintf(fd, "LogHost: %s:%u, %s\n", name(), port(), (connected(NOPING)) ? "connected" : "not connected");
 
362
}
 
363
 
 
364
void
 
365
LogHost::clear()
 
366
{
 
367
  // close an established connection and clear the state of this host
 
368
 
 
369
  disconnect();
 
370
 
 
371
  if (m_name)
 
372
    xfree(m_name);
 
373
  if (m_ipstr)
 
374
    xfree(m_ipstr);
 
375
  if (m_sock)
 
376
    delete m_sock;
 
377
  if (m_orphan_file)
 
378
    delete m_orphan_file;
 
379
 
 
380
  m_ip = 0;
 
381
  m_ipstr = NULL;
 
382
  m_name = NULL;
 
383
  m_port = 0;
 
384
  m_sock = NULL;
 
385
  m_sock_fd = -1;
 
386
  m_connected = false;
 
387
  m_orphan_file = NULL;
 
388
}
 
389
 
 
390
bool LogHost::authenticated()
 
391
{
 
392
  if (!connected(NOPING)) {
 
393
    Note("Cannot authenticate LogHost %s; not connected", name());
 
394
    return false;
 
395
  }
 
396
 
 
397
  Debug("log-host", "Authenticating LogHost %s ...", name());
 
398
  char *
 
399
    auth_key = Log::config->collation_secret;
 
400
  unsigned
 
401
    auth_key_len = (unsigned)::strlen(auth_key) + 1;    // incl null
 
402
  int
 
403
    bytes = m_sock->write(m_sock_fd, auth_key, auth_key_len);
 
404
  if ((unsigned) bytes != auth_key_len) {
 
405
    Debug("log-host", "... bad write on authenticate");
 
406
    return false;
 
407
  }
 
408
 
 
409
  Debug("log-host", "... authenticated");
 
410
  return true;
 
411
}
 
412
 
 
413
/*-------------------------------------------------------------------------
 
414
  LogHostList
 
415
  -------------------------------------------------------------------------*/
 
416
 
 
417
LogHostList::LogHostList()
 
418
{
 
419
}
 
420
 
 
421
LogHostList::~LogHostList()
 
422
{
 
423
  clear();
 
424
}
 
425
 
 
426
void
 
427
LogHostList::add(LogHost * object, bool copy)
 
428
{
 
429
  ink_assert(object != NULL);
 
430
  if (copy) {
 
431
    m_host_list.enqueue(NEW(new LogHost(*object)));
 
432
  } else {
 
433
    m_host_list.enqueue(object);
 
434
  }
 
435
}
 
436
 
 
437
unsigned
 
438
LogHostList::count()
 
439
{
 
440
  unsigned cnt = 0;
 
441
  for (LogHost * host = first(); host; host = next(host)) {
 
442
    cnt++;
 
443
  }
 
444
  return cnt;
 
445
}
 
446
 
 
447
void
 
448
LogHostList::clear()
 
449
{
 
450
  LogHost *host;
 
451
  while ((host = m_host_list.dequeue())) {
 
452
    delete host;
 
453
  }
 
454
}
 
455
 
 
456
int
 
457
LogHostList::write(LogBuffer * lb, size_t * to_disk, size_t * to_net, size_t * to_pipe)
 
458
{
 
459
  int total_bytes = 0;
 
460
  for (LogHost * host = first(); host; host = next(host)) {
 
461
    int bytes = host->write(lb, to_disk, to_net, to_pipe);
 
462
    if (bytes > 0)
 
463
      total_bytes += bytes;
 
464
  }
 
465
  return total_bytes;
 
466
}
 
467
 
 
468
void
 
469
LogHostList::display(FILE * fd)
 
470
{
 
471
  for (LogHost * host = first(); host; host = next(host)) {
 
472
    host->display(fd);
 
473
  }
 
474
}
 
475
 
 
476
bool LogHostList::operator==(LogHostList & rhs)
 
477
{
 
478
  LogHost *
 
479
    host;
 
480
  for (host = first(); host; host = next(host)) {
 
481
    LogHost *
 
482
      rhs_host;
 
483
    for (rhs_host = rhs.first(); rhs_host; rhs_host = next(host)) {
 
484
      if ((host->port() == rhs_host->port() &&
 
485
           (host->ip() && rhs_host->ip() &&
 
486
            (host->ip() == rhs_host->ip()))) ||
 
487
          (host->name() && rhs_host->name() &&
 
488
           (strcmp(host->name(), rhs_host->name()) == 0)) ||
 
489
          (host->ipstr() && rhs_host->ipstr() && (strcmp(host->ipstr(), rhs_host->ipstr()) == 0))) {
 
490
        break;
 
491
      }
 
492
    }
 
493
    if (rhs_host == NULL) {
 
494
      return false;
 
495
    }
 
496
  }
 
497
  return true;
 
498
}
 
499
 
 
500
int
 
501
LogHostList::do_filesystem_checks()
 
502
{
 
503
  for (LogHost * host = first(); host; host = next(host)) {
 
504
    if (host->do_filesystem_checks() < 0) {
 
505
      return -1;
 
506
    }
 
507
  }
 
508
  return 0;
 
509
}