HttpHandler::status_e RestAdminLogHandler::execute () {

  // .............................................................................
  // check the maximal log level to report
  // .............................................................................

  bool found1;
  string upto = StringUtils::tolower(_request->value("upto", found1));

  bool found2;
  string lvl = StringUtils::tolower(_request->value("level", found2));

  TRI_log_level_e ul = TRI_LOG_LEVEL_INFO;
  bool useUpto = true;
  string logLevel;
  
  // prefer level over upto
  if (found2) {
    logLevel = lvl;
    useUpto = false;
  }
  else if (found1) {
    logLevel = upto;
    useUpto = true;
  }

  if (found1 || found2) {
    if (logLevel == "fatal" || logLevel == "0") {
      ul = TRI_LOG_LEVEL_FATAL;
    }
    else if (logLevel == "error" || logLevel == "1") {
      ul = TRI_LOG_LEVEL_ERROR;
    }
    else if (logLevel == "warning" || logLevel == "2") {
      ul = TRI_LOG_LEVEL_WARNING;
    }
    else if (logLevel == "info" || logLevel == "3") {
      ul = TRI_LOG_LEVEL_INFO;
    }
    else if (logLevel == "debug" || logLevel == "4") {
      ul = TRI_LOG_LEVEL_DEBUG;
    }
    else if (logLevel == "trace" || logLevel == "5") {
      ul = TRI_LOG_LEVEL_TRACE;
    }
    else {
      generateError(HttpResponse::BAD, 
                    TRI_ERROR_HTTP_BAD_PARAMETER,
                    string("unknown '") + (found2 ? "level" : "upto") + "' log level: '" + logLevel + "'");
      return HANDLER_DONE;
    }
  }
  
  // .............................................................................
  // check the starting position
  // .............................................................................
  
  uint64_t start = 0;
  
  bool found;
  string s = _request->value("start", found);
  
  if (found) {
    start = StringUtils::uint64(s);
  }
  
  // .............................................................................
  // check the offset
  // .............................................................................
  
  uint64_t offset = 0;
  
  s = _request->value("offset", found);
  
  if (found) {
    offset = StringUtils::uint64(s);
  }
  
  // .............................................................................
  // check the size
  // .............................................................................
  
  uint64_t size = (uint64_t) -1;
  
  s = _request->value("size", found);
  
  if (found) {
    size = StringUtils::uint64(s);
  }
  
  // .............................................................................
  // check the sort direction
  // .............................................................................
  
  bool sortAscending = false;
  bool sortDescending = false;
  
  string sortdir = StringUtils::tolower(_request->value("sort", found));
  
  if (found) {
    if (sortdir == "asc") {
      sortAscending = true;
    }
    else if (sortdir == "desc") {
      sortDescending = true;
    }
    else {
      LOGGER_DEBUG << "unknown sort direction '" << sortdir << "'";
    }
  }
  
  // .............................................................................
  // check the search criteria
  // .............................................................................
  
  bool search = false;
  string searchString = StringUtils::tolower(_request->value("search", search));
  
  // .............................................................................
  // generate result
  // .............................................................................
  
  VariantArray* result = new VariantArray();
  
  VariantVector* lid = new VariantVector();
  result->add("lid", lid);
  
  VariantVector* level = new VariantVector();
  result->add("level", level);
  
  VariantVector* timestamp = new VariantVector();
  result->add("timestamp", timestamp);
  
  VariantVector* text = new VariantVector();
  result->add("text", text);
  
  TRI_vector_t * logs = TRI_BufferLogging(ul, start, useUpto);
  TRI_vector_t clean;
  
  TRI_InitVector(&clean, TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_log_buffer_t));
  
  for (size_t i = 0;  i < logs->_length;  ++i) {
    TRI_log_buffer_t* buf = (TRI_log_buffer_t*) TRI_AtVector(logs, i);
    
    if (search) {
      string text = StringUtils::tolower(buf->_text);
     
      if (text.find(searchString) == string::npos) {
        continue;
      }
    }
    
    TRI_PushBackVector(&clean, buf);
  }
  
  result->add("totalAmount", new VariantUInt64(clean._length));
  
  size_t length = clean._length;
  
  if (offset >= length) {
    length = 0;
    offset = 0;
  }
  else if (offset > 0) {
    length -= offset;
  }

  // restrict to at most <size> elements
  if (length > size) {
    length = size;
  }

  if (sortAscending) {
    qsort(((char*) TRI_BeginVector(&clean)) + offset * sizeof(TRI_log_buffer_t),
          length,
          sizeof(TRI_log_buffer_t),
          LidCompareAsc);
  }
  else if (sortDescending) {
    qsort(((char*) TRI_BeginVector(&clean)) + offset * sizeof(TRI_log_buffer_t),
          length,
          sizeof(TRI_log_buffer_t),
          LidCompareDesc);
  }
  
  for (size_t i = 0;  i < length;  ++i) {
    TRI_log_buffer_t* buf = (TRI_log_buffer_t*) TRI_AtVector(&clean, offset + i);
    uint32_t l = 0;
    
    switch (buf->_level) {
      case TRI_LOG_LEVEL_FATAL:  l = 0; break;
      case TRI_LOG_LEVEL_ERROR:  l = 1; break;
      case TRI_LOG_LEVEL_WARNING:  l = 2; break;
      case TRI_LOG_LEVEL_INFO:  l = 3; break;
      case TRI_LOG_LEVEL_DEBUG:  l = 4; break;
      case TRI_LOG_LEVEL_TRACE:  l = 5; break;
    }
    
    lid->add(new VariantUInt64(buf->_lid));
    level->add(new VariantUInt32(l));
    timestamp->add(new VariantUInt32(buf->_timestamp));
    text->add(new VariantString(buf->_text));
  }
  
  TRI_FreeBufferLogging(logs);
  TRI_DestroyVector(&clean);
  
  generateResult(result);
  return HANDLER_DONE;
}