-------------------------------------------------------------------------
-- $Author: fpina $
-- $Revision: 161412 $  - $Date: 2015-01-29 11:09:11 -0200 (Thu, 29 Jan 2015) $
-------------------------------------------------------------------------

PLATFORM = ""

--
-- Configurações específicas de plataformas
--
CNF_LIBRARY = {}
CNF_LIBRARY.remote_shell = "ssh -x "
--CNF_LIBRARY.remote_shell = "rsh "

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Windows" ] = {}
CNF_LIBRARY[ "Windows" ].collect_function = function(sdata)
  return 0, 0
end
CNF_LIBRARY[ "Windows" ].processes_formats = {}

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux24" ] = {}
CNF_LIBRARY[ "Linux24" ].processes_formats = {
   process_pid = "pid",
   parent_process_pid = "ppid",
   command = "comm",
   state = "state",
   processor_id = "cpu",
   ram_memory_used = "vsz",
   cpu_percentage = "pcpu",
   cpu_time = "time",
   wall_time = "etime",
}
CNF_LIBRARY[ "Linux24" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b -n1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b -n1"' -- nó de cluster
   -- end
   local load_patt = ".*load%s+average%s*:%s*(%d+[,%.]%d+)%s*%,%s*(%d+[,%.]%d+)"..
                     "%s*%,%s*(%d+[,%.]%d+)%D.*"
   --local memo_patt = ".*%D(%d+)([KkMmGg])%s+free,%s.*%D(%d+)([KkMmGg])%s+free%s.*"
   local memo_patt = ".*%D(%d+)([KkMmGg])%s+used,%s.*%D(%d+)([KkMmGg])%s+used,%s.*"
   local l1, l5, l15, mr, ur, ms, us = CNF:pattern_function(
                                            sdata, comm, load_patt, memo_patt )

   mr = tonumber(mr)
   ms = tonumber(ms)
   if mr then
      mr = CNF:MemValueToBytes(mr, ur)
   end
   if mr then
      ms = CNF:MemValueToBytes(ms, us)
   end

   local memo_load = { mr, ms}

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   return memo_load, load_perc
end

CNF_LIBRARY[ "Linux24" ].getmem = function(sdata)
   if sdata.memory_info then
      return sdata.memory_info
   end

   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b -n1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b -n1"' -- nó de cluster
   -- end
   local mem_patt = ".*%D(%d+)([KkMmGg])%s+av,%s.*%D(%d+)([KkMmGg])%s+av,%s.*"
   local fname = os.tmpname()
   local csh_command = comm..'|head -n15 > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local str_aux = string.gsub( str, mem_patt, "%1 %2 %3 %4" )
   local ram = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local uram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
   local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
   local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+).*", "%4" )

   ram = tonumber(ram)
   swap = tonumber(swap)
   if ram then
     ram = CNF:MemValueToBytes(ram, uram)
   end
   if swap then
     swap = CNF:MemValueToBytes(swap, uswap)
   end

   local memo = { ram, swap}
   sdata.memory_info = memo

   return memo
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux24g3" ] = {}
CNF_LIBRARY[ "Linux24g3" ].collect_function =
  CNF_LIBRARY[ "Linux24" ].collect_function
CNF_LIBRARY[ "Linux24g3" ].processes_formats =
  CNF_LIBRARY[ "Linux24" ].processes_formats
CNF_LIBRARY[ "Linux24g3" ].getmem =
  CNF_LIBRARY[ "Linux24" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux24g3_64" ] = {}
CNF_LIBRARY[ "Linux24g3_64" ].collect_function =
  CNF_LIBRARY[ "Linux24" ].collect_function
CNF_LIBRARY[ "Linux24g3_64" ].processes_formats =
  CNF_LIBRARY[ "Linux24" ].processes_formats
CNF_LIBRARY[ "Linux24g3_64" ].getmem =
  CNF_LIBRARY[ "Linux24" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux22" ] = {}
CNF_LIBRARY[ "Linux22" ].collect_function =
  CNF_LIBRARY[ "Linux24" ].collect_function
CNF_LIBRARY[ "Linux22" ].processes_formats =
  CNF_LIBRARY[ "Linux24" ].processes_formats
CNF_LIBRARY[ "Linux22" ].getmem =
  CNF_LIBRARY[ "Linux24" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26" ] = {}
CNF_LIBRARY[ "Linux26" ].collect_function =
  CNF_LIBRARY[ "Linux24" ].collect_function
CNF_LIBRARY[ "Linux26" ].processes_formats =
  CNF_LIBRARY[ "Linux24" ].processes_formats
CNF_LIBRARY[ "Linux26" ].getmem = function(sdata)
   if sdata.memory_info then
      return sdata.memory_info
   end

   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b -n1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b -n1"' -- nó de cluster
   -- end
   local mem_patt = ".*%D(%d+)([KkMmGg])%s+total,%s.*%D(%d+)([KkMmGg])%s+total,%s.*"
   local fname = os.tmpname()
   local csh_command = comm..'|head -n15 > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local str_aux = string.gsub( str, mem_patt, "%1 %2 %3 %4" )
   local ram = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local uram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
   local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
   local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+).*", "%4" )

   ram = tonumber(ram)
   swap = tonumber(swap)
   if ram then
     ram = CNF:MemValueToBytes(ram, uram)
   end
   if swap then
     swap = CNF:MemValueToBytes(swap, uswap)
   end

   local memo = { ram, swap}
   sdata.memory_info = memo

   return memo
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26" ].collect_process_io_info_function = function()
  sdata = {}

  -- Coleta métricas de histórico somente no caso da propriedade
  -- enable_historic estar ativada no arquivo de configuração do SGA.
  CNF_LIBRARY[ "Linux26" ].collect_process_disk_info_function(sdata)
  CNF_LIBRARY[ "Linux26" ].collect_process_net_info_function(sdata)

  return sdata
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26" ].collect_process_cpu_info_function = function(sdata)
  pidFile = "/proc/"..sdata.process_pid.."/stat"

  fd = io.open(pidFile)
  if fd then
    -- realiza o parser: pid (comm) state ppid x x x x x x x x x user_time
    -- sys_time x x x x x x start_time virtual_mem resident_mem
    -- x x x x x x x x x x x x x x processor_id
    for line in fd:lines() do
      pattern = "%s*%-*%d+%s+%([^)]+%)%s+%a%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)%s+(%d+)%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%-*%d+%s+%d+%s+(%d+)%s+(%-*%d+)%.*"
      local fields = {string.find(line, pattern)}

      sdata["user_time"] = fields[3]/100
      sdata["system_time"] = fields[4]/100
      sdata["virtual_memory"] = fields[5]/1024
    end
    fd:close()

    return sdata["process_pid"]
  else
    return
  end
end

-- ..........................................................................
-- Método para a coleta de métricas de execução de algoritmos. Essas
-- métricas alimentam um arquivo de histórico o qual é utilizado para
-- se estimar o comportamento de execução dos algoritmos.
-- ..........................................................................

CNF_LIBRARY[ "Linux26" ].collect_process_net_info_function = function(sdata)
  file = "/proc/net/dev"

  fd = io.open(file)
  if fd then
    -- lê os cabeçalhos
    fd:read()
    fd:read()
    -- realiza o parser: interface_name bytes_in x x x x x x x bytes_out
    line = fd:read("*line")
    while line ~= NULL do
      _,j,interfaceName = string.find(line,"%s*(%w+):")
      -- @TODO Rever o uso de SGAD_CONF
      if interfaceName == SGAD_CONF.net_interface_name then
        line = string.sub(line, j+1)
        pattern = "%s*(%d+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)"
        _,_,bytes_in,bytes_out = string.find(line, pattern)
        sdata["bytes_in"] = bytes_in / 1024
        sdata["bytes_out"] = bytes_out / 1024
        break
      end
      line = fd:read("*line")
    end
    fd:close()
  end
end

-- ..........................................................................
-- Método para a coleta de métricas de execução de algoritmos. Essas
-- métricas alimentam um arquivo de histórico o qual é utilizado para
-- se estimar o comportamento de execução dos algoritmos.
-- ..........................................................................

CNF_LIBRARY[ "Linux26" ].collect_process_disk_info_function = function(sdata)
  file = "/proc/diskstats"

  fd = io.open(file)
  if fd then
    -- realiza o parser: x x partition_name x x disk_read_sectors x x x
    -- disk_write_sectors
    line = fd:read("*line")
    while line ~= NULL do
      _,j,partitionName = string.find(line, "%s+%d+%s+%d+%s+(%a+)")
      -- @TODO Rever o uso de SGAD_CONF
      if partitionName == SGAD_CONF.partition_name then
        line = string.sub(line, j+1)
        pattern = "%s+%d+%s+%d+%s+(%d+)%s+%d+%s+%d+%s+%d+%s+(%d+)"
        _,_,disk_bytes_read,disk_bytes_write = string.find(line, pattern)
        sdata["disk_bytes_read"] = disk_bytes_read * 512 / 1024
        sdata["disk_bytes_write"] = disk_bytes_write * 512 / 1024
        break
      end
      line = fd:read("*line")
    end
    fd:close()
  end
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26g4" ] = {}
CNF_LIBRARY[ "Linux26g4" ].collect_function =
  CNF_LIBRARY[ "Linux26" ].collect_function
CNF_LIBRARY[ "Linux26g4" ].processes_formats =
  CNF_LIBRARY[ "Linux26" ].processes_formats
CNF_LIBRARY[ "Linux26g4" ].getmem =
  CNF_LIBRARY[ "Linux26" ].getmem
CNF_LIBRARY[ "Linux26g4" ].collect_process_cpu_info_function =
  CNF_LIBRARY[ "Linux26" ].collect_process_cpu_info_function
CNF_LIBRARY[ "Linux26g4" ].collect_process_io_info_function =
  CNF_LIBRARY[ "Linux26" ].collect_process_io_info_function

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26_64" ] = {}
CNF_LIBRARY[ "Linux26_64" ].collect_function =
  CNF_LIBRARY[ "Linux26" ].collect_function
CNF_LIBRARY[ "Linux26_64" ].processes_formats =
  CNF_LIBRARY[ "Linux26" ].processes_formats
CNF_LIBRARY[ "Linux26_64" ].getmem =
  CNF_LIBRARY[ "Linux26" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26g4_64" ] = {}
CNF_LIBRARY[ "Linux26g4_64" ].collect_function =
  CNF_LIBRARY[ "Linux26" ].collect_function
CNF_LIBRARY[ "Linux26g4_64" ].processes_formats =
  CNF_LIBRARY[ "Linux26" ].processes_formats
CNF_LIBRARY[ "Linux26g4_64" ].getmem =
  CNF_LIBRARY[ "Linux26" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux26_ia64" ] = {}
CNF_LIBRARY[ "Linux26_ia64" ].collect_function =
  CNF_LIBRARY[ "Linux26" ].collect_function
CNF_LIBRARY[ "Linux26_ia64" ].processes_formats =
  CNF_LIBRARY[ "Linux26" ].processes_formats
CNF_LIBRARY[ "Linux26_ia64" ].getmem =
  CNF_LIBRARY[ "Linux26" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux35" ] = {}
CNF_LIBRARY[ "Linux35" ].pattern_function = function( sdata, comm, lpatt, mpatt )
  local fname = os.tmpname()
  --local csh_command = 'csh -c "'..comm..' >! '..fname..'"'
  local csh_command = comm..'|head -n15 > '..fname
  servermanager.writeMsg("Executando coleta com ["..csh_command.."]")

  os.execute( csh_command )

  local fd = io.open(fname, "r")
  if not fd then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  local str = fd:read("*a")
  fd:close()

  if not str then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  str = string.gsub( str, "%c", "" )

  os.remove(fname)

  local str_aux = string.gsub( str, lpatt, "%1 %2 %3" )
  str_aux = string.gsub( str_aux, ",", "." )
  local load1 = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
  local load5 = string.gsub( str_aux, "(%S+)%s+(%S+)%s+.*", "%2" )
  local load15 = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+).*", "%3" )

  str_aux = string.gsub( str, mpatt, "%1 %2 %3" )
  local unit = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
  local ram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
  local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+).*", "%3" )

  return load1, load5, load15, ram, unit, swap, unit
end

CNF_LIBRARY[ "Linux35" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b -n1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b -n1"' -- nó de cluster
   -- end
   local load_patt = ".*load%s+average%s*:%s*(%d+[,%.]%d+)%s*%,%s*(%d+[,%.]%d+)"..
                     "%s*%,%s*(%d+[,%.]%d+)%D.*"
   --local memo_patt = ".*%D(%d+)([KkMmGg])%s+free,%s.*%D(%d+)([KkMmGg])%s+free%s.*"
   local memo_patt = ".*([KkMmGg])iB.*%D(%d+)%s+used,%s.*%D(%d+)%s+used,%s.*"
   local l1, l5, l15, mr, ur, ms, us = CNF_LIBRARY[ "Linux35" ].pattern_function(
                                            sdata, comm, load_patt, memo_patt )

   mr = tonumber(mr)
   ms = tonumber(ms)
   if mr then
      mr = CNF:MemValueToBytes(mr, ur)
   end
   if mr then
      ms = CNF:MemValueToBytes(ms, us)
   end

   local memo_load = { mr, ms}

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   return memo_load, load_perc
end

CNF_LIBRARY[ "Linux35" ].processes_formats =
  CNF_LIBRARY[ "Linux26" ].processes_formats
CNF_LIBRARY[ "Linux35" ].getmem = function(sdata)
   if sdata.memory_info then
      return sdata.memory_info
   end

   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b -n1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b -n1"' -- nó de cluster
   -- end
   local mem_patt = ".*([KkMmGg])iB.*%D(%d+)%s+total,%s.*%D(%d+)%s+total,%s.*"
   local fname = os.tmpname()
   local csh_command = comm..'|head -n15 > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local str_aux = string.gsub( str, mem_patt, "%1 %2 %3" )
   local unit = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local ram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
   local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+).*", "%3" )


   ram = tonumber(ram)
   swap = tonumber(swap)
   if ram then
     ram = CNF:MemValueToBytes(ram, unit)
   end
   if swap then
     swap = CNF:MemValueToBytes(swap, unit)
   end

   local memo = { ram, swap}
   sdata.memory_info = memo

   return memo
end

CNF_LIBRARY[ "Linux35" ].collect_process_cpu_info_function =
  CNF_LIBRARY[ "Linux26" ].collect_process_cpu_info_function
CNF_LIBRARY[ "Linux35" ].collect_process_io_info_function =
  CNF_LIBRARY[ "Linux26" ].collect_process_io_info_function

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Linux35_64" ] = {}
CNF_LIBRARY[ "Linux35_64" ].collect_function =
  CNF_LIBRARY[ "Linux35" ].collect_function
CNF_LIBRARY[ "Linux35_64" ].processes_formats =
  CNF_LIBRARY[ "Linux35" ].processes_formats
CNF_LIBRARY[ "Linux35_64" ].getmem =
  CNF_LIBRARY[ "Linux35" ].getmem
CNF_LIBRARY[ "Linux35_64" ].collect_process_cpu_info_function =
  CNF_LIBRARY[ "Linux35" ].collect_process_cpu_info_function
CNF_LIBRARY[ "Linux35_64" ].collect_process_io_info_function =
  CNF_LIBRARY[ "Linux35" ].collect_process_io_info_function

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Darwin97" ] = {}
CNF_LIBRARY[ "Darwin97" ].processes_command = "ps -Aco"
CNF_LIBRARY[ "Darwin97" ].processes_formats = {
   process_pid = "pid=pid",
   parent_process_pid = "ppid=ppid",
   command = "command=command",
   state = "state=state",
   processor_id = "cpu=cpu",
   ram_memory_used = "vsz=vsz",
   cpu_percentage = "pcpu",
   cpu_time = "time=time",
}
CNF_LIBRARY[ "Darwin97" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -S -l1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -S -l1"' -- nó de cluster
   -- end
   local load_patt = ".*Load%s+Avg%s*:%s*(%d+[,%.]%d+)%s*%,%s*(%d+[,%.]%d+)"..
                     "%s*%,%s*(%d+[,%.]%d+)%D.*"
   local memo_patt = ".*PhysMem:.-(%d+%.?%d*)([KkMmGg])%s+free.*"..
     "Swap:.-(%d+%.?%d*)([KkMmGg])%s+free.*"
   local l1, l5, l15, mr, ur, ms, us = CNF:pattern_function(
                                            sdata, comm, load_patt, memo_patt )
   local memo = CNF_LIBRARY[ "Darwin97" ].getmem(sdata)
   local memo_load1, memo_load2
   if memo then
      mr = tonumber(mr)
      ms = tonumber(ms)
      if mr and memo[1] then
         mr = CNF:MemValueToBytes(mr, ur)
         memo_load1 = memo[1] - mr
      end
     if ms and memo[2] then
        ms = CNF:MemValueToBytes(ms, us)
        memo_load2 = memo[2] - ms
     end
   end

   local memo_load = { memo_load1, memo_load2 }

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   return memo_load, load_perc
end

CNF_LIBRARY[ "Darwin97" ].getmem = function(sdata)
   local mem2bytes = function(mem, unit)
     mem = tonumber(mem)
     if mem then
       mem = CNF:MemValueToBytes(mem, unit)
     end
     return mem
   end
   if sdata.memory_info then
      return sdata.memory_info
   end

   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -S -l1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -S -l1"' -- nó de cluster
   -- end
   local mem_patt = ".*PhysMem:.-(%d+%.?%d*)([KkMmGg])%s+used,%s+(%d+%.?%d*)([KkMmGg])%s+free.*Swap:.-(%d+%.?%d*)([KkMmGgBb]?)%s+%+%s+(%d+%.?%d*)([KkMmGg])%s+free.*"

   local fname = os.tmpname()
   local csh_command = comm..'|head -n15 > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local _,_, ramused, uramused, ramfree, uramfree, swapused, uswapused, swapfree, uswapfree = string.find(str, mem_patt)

   ramused = mem2bytes(ramused,uramused)
   ramfree = mem2bytes(ramfree,uramfree)
   local ram
   if ramused and ramfree then
     ram = ramused + ramfree
   end
   swapused = mem2bytes(swapused,uswapused)
   swapfree = mem2bytes(swapfree,uswapfree)
   local swap
   if swapused and swapfree then
     swap = swapused + swapfree
   end

   local memo = { ram, swap}
   sdata.memory_info = memo

   return memo
end

CNF_LIBRARY[ "Darwin13" ] = {}
CNF_LIBRARY[ "Darwin13" ].processes_formats =
  CNF_LIBRARY[ "Darwin97" ].processes_formats

CNF_LIBRARY[ "Darwin13" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -S -l1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -S -l1"' -- nó de cluster
   -- end
   local load_patt = ".*Load%s+Avg%s*:%s*(%d+[,%.]%d+)%s*%,%s*(%d+[,%.]%d+)"..
                     "%s*%,%s*(%d+[,%.]%d+)%D.*"
   -- local memo_patt = ".*PhysMem:.-(%d+%.?%d*)([KkMmGg])%s+free.*"..
   --   "Swap:.-(%d+%.?%d*)([KkMmGg])%s+free.*"
   local memo_patt = ".*PhysMem:.-%s(%d+%.?%d*)([KkMmGg])%s+unused.*"..
     "Swap:.-(%d+%.?%d*)([KkMmGg])%s+free.*"
   local l1, l5, l15, mr, ur, ms, us = CNF:pattern_function(
                                            sdata, comm, load_patt, memo_patt )

   local memo = CNF_LIBRARY[ "Darwin13" ].getmem(sdata)
   local memo_load1, memo_load2
   if memo then
      mr = tonumber(mr)
      ms = tonumber(ms)
      if mr and memo[1] then
         mr = CNF:MemValueToBytes(mr, ur)
         memo_load1 = memo[1] - mr
      end
     if ms and memo[2] then
        ms = CNF:MemValueToBytes(ms, us)
        memo_load2 = memo[2] - ms
     end
   end

   local memo_load = { memo_load1, memo_load2 }

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15 = tonumber(l15)

   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   return memo_load, load_perc
end

CNF_LIBRARY[ "Darwin13" ].getmem = function(sdata)
   local mem2bytes = function(mem, unit)
     mem = tonumber(mem)
     if mem then
       mem = CNF:MemValueToBytes(mem, unit)
     end
     return mem
   end
   if sdata.memory_info then
      return sdata.memory_info
   end

   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -S -l1"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -S -l1"' -- nó de cluster
   -- end
   -- local mem_patt = ".*PhysMem:.-(%d+%.?%d*)([KkMmGg])%s+used,%s+(%d+%.?%d*)([KkMmGg])%s+free.*Swap:.-(%d+%.?%d*)([KkMmGgBb]?)%s+%+%s+(%d+%.?%d*)([KkMmGg])%s+free.*"
   local mem_patt = ".*PhysMem:.-(%d+%.?%d*)([KkMmGg])%s+used.+%s(%d+%.?%d*)([KkMmGg])%s+unused.*Swap:.-(%d+%.?%d*)([KkMmGgBb])%s+%+%s+(%d+%.?%d*)([KkMmGg])%s+free.*"

   local fname = os.tmpname()
   local csh_command = comm..'|head -n12 > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local _,_, ramused, uramused, ramfree, uramfree, swapused, uswapused, swapfree, uswapfree = string.find(str, mem_patt)

   ramused = mem2bytes(ramused,uramused)
   ramfree = mem2bytes(ramfree,uramfree)
   local ram
   if ramused and ramfree then
     ram = ramused + ramfree
   end
   swapused = mem2bytes(swapused,uswapused)
   swapfree = mem2bytes(swapfree,uswapfree)
   local swap
   if swapused and swapfree then
     swap = swapused + swapfree
   end

   local memo = {ram, swap}
   sdata.memory_info = memo

   return memo
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "Darwin98" ] = CNF_LIBRARY[ "Darwin97" ]
CNF_LIBRARY[ "Darwin104x86" ] = CNF_LIBRARY[ "Darwin97" ]
CNF_LIBRARY[ "MacOS106" ] = CNF_LIBRARY[ "Darwin97" ]
CNF_LIBRARY[ "MacOS107" ] = CNF_LIBRARY[ "Darwin97" ]
CNF_LIBRARY[ "MacOS108" ] = CNF_LIBRARY[ "Darwin97" ]
CNF_LIBRARY[ "MacOS109" ] = CNF_LIBRARY[ "Darwin13" ]
CNF_LIBRARY[ "MacOS1010" ] = CNF_LIBRARY[ "Darwin13" ]

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "IRIX6465" ] = {}
CNF_LIBRARY[ "IRIX6465" ].processes_formats = {
   process_pid = "pid",
   parent_process_pid = "ppid",
   command = "comm",
   state = "state",
   processor_id = "cpu",
   ram_memory_used = "vsz",
   cpu_percentage = "pcpu",
   cpu_time = "time",
   wall_time = "etime",
}
CNF_LIBRARY[ "IRIX6465" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b"' -- nó de cluster
   -- end
   local memo = CNF_LIBRARY[ "IRIX6465" ].getmem(sdata)
   local load_patt = ".*load averages:%s*(%d+%.%d+)%s+(%d+%.%d+)"..
                     "%s+(%d+%.%d+)%D.*"

   local memo_patt = ".*%D(%d+)([KkMmGg])%s+free,.*%D+(%d+)([KkMmGg])%s+free%s+swap.*"

   local l1, l5, l15, mr, ur, ms, us = CNF:pattern_function(
                                             sdata, comm, load_patt, memo_patt )

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   local memo_load1, memo_load2
   if memo then
      mr = tonumber(mr)
      ms = tonumber(ms)
      if mr and memo[1] then
         mr = CNF:MemValueToBytes(mr, ur)
         memo_load1 = memo[1] - mr
      end
     if ms and memo[2] then
        ms = CNF:MemValueToBytes(ms, us)
        memo_load2 = memo[2] - ms
     end
   end

   return { memo_load1, memo_load2}, load_perc
end

CNF_LIBRARY[ "IRIX6465" ].getmem = function(sdata)
   if sdata.memory_info then
      return sdata.memory_info
   end

   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b"' -- nó de cluster
   -- end
   local mem_patt = ".*%D(%d+)([KkMmGg])%s+max,.*%D+(%d+)([KkMmGg])%s+swap,.*"
   local fname = os.tmpname()
   local csh_command = comm..'|head -n10 > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )


   os.remove(fname)

   local str_aux = string.gsub( str, mem_patt, "%1 %2 %3 %4" )
   local ram = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local uram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
   local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
   local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+).*", "%4" )

   ram = tonumber(ram)
   swap = tonumber(swap)

   ram = CNF:MemValueToBytes(ram, uram)
   swap = CNF:MemValueToBytes(swap, uswap)

   local memo = { ram, swap}
   sdata.memory_info = memo

   return memo
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "AIX43" ] = {}
CNF_LIBRARY[ "AIX43" ].processes_formats = {
   process_pid = "pid",
   parent_process_pid = "ppid",
   command = "comm",
   state = "state",
   processor_id = "bnd",
   ram_memory_used = "vsz",
   cpu_percentage = "pcpu",
   cpu_time = "time",
   wall_time = "etime",
}

CNF_LIBRARY[ "AIX43" ].get_load = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "uptime "    -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "uptime"' -- nó de cluster
   -- end

   local fname = os.tmpname()
   local csh_command = comm..'|head -n15 > '..fname
   servermanager.writeMsg("Executando coleta com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local lpatt = ".*load%s+average%s*:%s*(%d+%.%d+)%s*,%s*(%d+%.%d+)"..
                 "%s*,%s*(%d+%.%d+).*"

   local str_aux = string.gsub( str, lpatt, "%1 %2 %3" )
   str_aux = string.gsub( str_aux, ",", "." )
   local l1 = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local l5 = string.gsub( str_aux, "(%S+)%s+(%S+)%s+.*", "%2" )
   local l15 = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+).*", "%3" )

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end

   return { l1, l5, l15 }
end

CNF_LIBRARY[ "AIX43" ].get_freemem = function( sdata)
   local env = os.getenv("PWD") or "."
   local comm = string.format("cd %s && ./collect_aix_data", env)
   local rsh = CNF_LIBRARY.remote_shell
   -- if not sdata.localhost then
   --    comm = rsh..sdata.name..' "'..comm..'"' -- nó de cluster
   -- end
   local fname = os.tmpname()
   local csh_command = comm..' > '..fname
   servermanager.writeMsg("Executando coleta com ["..csh_command .."]")

   os.execute( csh_command  )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub(str, "%c", "")

   os.remove(fname)

   --Real free(MB),Virtual free(MB)
   local mpatt = ".*MEM,.*Real free%(([KkMmGg])B%),Virtual free%(([KkMmGg])B%).*MEM,[^,]*,[0-9|.]+,[0-9|.]+,([0-9|.]+),([0-9|.]+),[0-9|.]+,[0-9|.]+.*"

   local str_aux = string.gsub( str, mpatt, "%1 %2 %3 %4" )
   local uram = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
   local ram = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
   local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+).*", "%4" )

   ram = tonumber(ram)
   swap = tonumber(swap)

   if ram then
      ram = CNF:MemValueToBytes(ram, uram)
   end
   if swap then
      swap = CNF:MemValueToBytes(swap, uswap)
   end

   return {ram, swap}
end

CNF_LIBRARY[ "AIX43" ].collect_function = function(sdata)
   local memo = CNF_LIBRARY[ "AIX43" ].getmem(sdata)
   local memo_free
   local memo_load1, memo_load2
   if memo then
      memo_free = CNF_LIBRARY[ "AIX43" ].get_freemem(sdata)
      if memo[1] and memo_free and memo_free[1] then
         memo_load1 = memo[1] - memo_free[1]
      end
      if memo[2] and memo_free and memo_free[2] then
         memo_load2 = memo[2] - memo_free[2]
      end
   end
   local load_perc = CNF_LIBRARY[ "AIX43" ].get_load(sdata)

   return { memo_load1, memo_load2}, load_perc
end

CNF_LIBRARY[ "AIX43" ].getmem = function(sdata)
   if sdata.memory_info then
      return sdata.memory_info
   end

   local env = os.getenv("PWD") or "."
   local comm = string.format("cd %s && ./collect_aix_data", env)
   local rsh = CNF_LIBRARY.remote_shell
   -- if not sdata.localhost then
   --    comm = rsh..sdata.name..' "'..comm..'"' -- nó de cluster
   -- end
   --Real total(MB),Virtual total(MB)
   local mem_patt = ".*MEM,.*Real total%(([KkMmGg])B%),Virtual total%(([KkMmGg])B%).*MEM,[^,]*,[0-9|.]+,[0-9|.]+,[0-9|.]+,[0-9|.]+,([0-9|.]+),([0-9|.]+).*"
   local fname = os.tmpname()
   local csh_command = comm..' > '..fname
   servermanager.writeMsg("Coletando info com ["..csh_command.."]")

   os.execute( csh_command )

   local fd = io.open(fname, "r")
   if not fd then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   local str = fd:read("*a")
   fd:close()

   if not str then
      servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
      return
   end
   str = string.gsub( str, "%c", "" )

   os.remove(fname)

   local str_aux = string.gsub( str, mem_patt, "%1 %2 %3 %4" )
   local uram = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
   local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
   local ram = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
   local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+).*", "%4" )

   ram = tonumber(ram)
   swap = tonumber(swap)

   if ram then
      ram = CNF:MemValueToBytes(ram, uram)
   end
   if swap then
      swap = CNF:MemValueToBytes(swap, uswap)
   end

   local memo = { ram, swap}
   sdata.memory_info = memo

   return memo
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "AIX52" ] = {}
CNF_LIBRARY[ "AIX52" ].collect_function =
  CNF_LIBRARY[ "AIX43" ].collect_function
CNF_LIBRARY[ "AIX52" ].processes_formats =
  CNF_LIBRARY[ "AIX43" ].processes_formats
CNF_LIBRARY[ "AIX52" ].getmem =
  CNF_LIBRARY[ "AIX43" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "SunOS58" ] = {}
CNF_LIBRARY[ "SunOS58" ].processes_formats = {
   process_pid = "pid",
   parent_process_pid = "ppid",
   command = "comm",
   state = "s",
   processor_id = "psr",
   ram_memory_used = "vsz",
   cpu_percentage = "pcpu",
   cpu_time = "time",
   wall_time = "etime",
}
CNF_LIBRARY[ "SunOS58" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top -b"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top -b"' -- nó de cluster
   -- end
   local memo = CNF_LIBRARY[ "SunOS58" ].getmem(sdata)
   local load_patt = ".*load%s+averages%s*:%s*(%d+[,%.]%d+)%s*%,%s*(%d+[,%.]%d+)"..
                     "%s*%,%s*(%d+[,%.]%d+)%D.*"

   local memo_patt = ".*%D(%d+)([KkMmGg])%s+free,.*%D+(%d+)([KkMmGg])%s+swap%s+free.*"

   local l1, l5, l15, mr, ur, ms, us = CNF:pattern_function(
      sdata, comm, load_patt, memo_patt )

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   local memo_load1, memo_load2
   if memo then
      mr = tonumber(mr)
      ms = tonumber(ms)
      if mr and memo[1] then
         mr = CNF:MemValueToBytes(mr, ur)
         memo_load1= memo[1] - mr
      end
      if ms and memo[2] then
         ms = CNF:MemValueToBytes(ms, us)
        memo_load2 = memo[2] - ms
      end
   end

   return {memo_load1, memo_load2}, load_perc
end

CNF_LIBRARY[ "SunOS58" ].getmem = function(sdata) -- XXX
  if sdata.memory_info then
     return sdata.memory_info
  end

  local comm
  local rsh = CNF_LIBRARY.remote_shell
  -- if sdata.localhost then
    comm = "top -b"  -- nó principal
  -- else
  --   comm = rsh..sdata.name..' "top -b"' -- nó de cluster
  -- end
  local mem_patt = ".*%D(%d+)([KkMmGg])%s+real,.*%D+(%d+)([KkMmGg])%s+swap%s+in%s+use,.*%D+(%d+)([KkMmGg])%s+swap%s+free.*"

  local fname = os.tmpname()
  local csh_command = comm..'|head -n10 > '..fname
  servermanager.writeMsg("Coletando info com ["..csh_command.."]")

  os.execute( csh_command )

  local fd = io.open(fname, "r")
  if not fd then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  local str = fd:read("*a")
  fd:close()

  if not str then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  str = string.gsub( str, "%c", "" )

  os.remove(fname)

  local str_aux = string.gsub( str, mem_patt, "%1 %2 %3 %4 %5 %6" )
  local ram = string.gsub( str_aux, "(%S+)%s.*", "%1" )
  local uram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
  local swapuse = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
  local uswapuse = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s.*", "%4" )
  local swapfree = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s.*", "%5" )
  local uswapfree = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s(%S+).*", "%6" )
  local swap

  ram = tonumber(ram)
  swapuse = tonumber(swapuse)
  swapfree = tonumber(swapfree)

  if ram then
     ram = CNF:MemValueToBytes(ram, uram)
  end
  if swapuse then
     swapuse = CNF:MemValueToBytes(swapuse, uswapuse)
     swap = swapuse
  end
  if swapfree then
     swapfree = CNF:MemValueToBytes(swapfree, uswapfree)
     swap = (swapuse or 0) + swapfree
  end

  local memo = { ram, swap}
  sdata.memory_info = memo

  return memo
end

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "SunOS57" ] = {}
CNF_LIBRARY[ "SunOS57" ].collect_function =
  CNF_LIBRARY[ "SunOS58" ].collect_function
CNF_LIBRARY[ "SunOS57" ].processes_formats =
  CNF_LIBRARY[ "SunOS58" ].processes_formats
CNF_LIBRARY[ "SunOS57" ].getmem =
  CNF_LIBRARY[ "SunOS58" ].getmem

-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "SunOS510" ] = {}
CNF_LIBRARY[ "SunOS510" ].processes_formats = {
   process_pid = "pid",
   parent_process_pid = "ppid",
   command = "comm",
   state = "s",
   processor_id = "psr",
   ram_memory_used = "vsz",
   cpu_percentage = "pcpu",
   cpu_time = "time",
   wall_time = "etime",
}
CNF_LIBRARY[ "SunOS510" ].collect_function = function(sdata)
   local comm
   local rsh = CNF_LIBRARY.remote_shell
   -- if sdata.localhost then
      comm = "top"  -- nó principal
   -- else
   --    comm = rsh..sdata.name..' "top"' -- nó de cluster
   -- end
   local memo = CNF_LIBRARY[ "SunOS510" ].getmem(sdata)
   local load_patt = ".*load%s+averages%s*:%s*(%d+[,%.]%d+)%s*%,%s*(%d+[,%.]%d+)"..
                     "%s*%,%s*(%d+[,%.]%d+)%D.*"

   local memo_patt = ".*%D(%d+)([KkMmGg])%s+free%s+mem,.*%D+(%d+)([KkMmGg])%s+free%s+swap.*"

   local l1, l5, l15, mr, ur, ms, us = CNF:pattern_function(
      sdata, comm, load_patt, memo_patt )

   l1 = tonumber(l1)
   l5 = tonumber(l5)
   l15= tonumber(l15)
   -- if l1 then
   --    l1 = l1 / sdata.num_processors * 100
   -- end
   -- if l5 then
   --    l5 = l5 / sdata.num_processors * 100
   -- end
   -- if l15 then
   --    l15 = l15 / sdata.num_processors * 100
   -- end
   local load_perc =  { l1, l5, l15 }

   local memo_load1, memo_load2
   if memo then
      mr = tonumber(mr)
      ms = tonumber(ms)
      if mr and memo[1] then
         mr = CNF:MemValueToBytes(mr, ur)
         memo_load1= memo[1] - mr
      end
      if ms and memo[2] then
         ms = CNF:MemValueToBytes(ms, us)
        memo_load2 = memo[2] - ms
      end
   end

   return {memo_load1, memo_load2}, load_perc
end

CNF_LIBRARY[ "SunOS510" ].getmem = function(sdata) -- XXX
  if sdata.memory_info then
     return sdata.memory_info
  end

  local comm
  local rsh = CNF_LIBRARY.remote_shell
  -- if sdata.localhost then
    comm = "top"  -- nó principal
  -- else
  --   comm = rsh..sdata.name..' "top"' -- nó de cluster
  -- end
  local mem_patt = ".*%D(%d+)([KkMmGg])%s+phys%s+mem,.*%D+(%d+)([KkMmGg])%s+swap,.*%D+(%d+)([KkMmGg])%s+free%s+swap.*"

  local fname = os.tmpname()
  local csh_command = comm..'|head -n10 > '..fname
  servermanager.writeMsg("Coletando info com ["..csh_command.."]")

  os.execute( csh_command )

  local fd = io.open(fname, "r")
  if not fd then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  local str = fd:read("*a")
  fd:close()

  if not str then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  str = string.gsub( str, "%c", "" )

  os.remove(fname)

  local str_aux = string.gsub( str, mem_patt, "%1 %2 %3 %4 %5 %6" )
  local ram = string.gsub( str_aux, "(%S+)%s.*", "%1" )
  local uram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
  local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
  local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s.*", "%4" )

  ram = tonumber(ram)
  swap = tonumber(swap)

  if ram then
     ram = CNF:MemValueToBytes(ram, uram)
  end
  if swap then
     swap = CNF:MemValueToBytes(swap, uswap)
  end

  local memo = { ram, swap}
  sdata.memory_info = memo

  return memo
end
-- ..........................................................................
-- ..........................................................................
-- ..........................................................................

CNF_LIBRARY[ "SunOS510x86" ] = {}
CNF_LIBRARY[ "SunOS510x86" ].collect_function =
  CNF_LIBRARY[ "SunOS510" ].collect_function
CNF_LIBRARY[ "SunOS510x86" ].processes_formats =
  CNF_LIBRARY[ "SunOS510" ].processes_formats
CNF_LIBRARY[ "SunOS510x86" ].getmem =
  CNF_LIBRARY[ "SunOS510" ].getmem

-- ======================================================================
-- ======================================================================
-- ======================================================================
-- ======================================================================

PATTERNS = {}

-- Obtem os dados dinamicos do SGA

function PATTERNS.get_node(name)
  return SGA_DAEMON:getNode(name)
end

function PATTERNS.get_node_dynamic_data( name )
   local sdata = PATTERNS.get_node(name) -- XXX (trocar)
   -- local cnf = CNF_LIBRARY[ sdata.platform_os ]
   local cnf = CNF_LIBRARY[PLATFORM]
   if not cnf then
      return nil, nil
   end
   return cnf.collect_function(sdata)
end

function PATTERNS.get_node_static_data( name )
   local node = PATTERNS.get_node(name) -- XXX (trocar)
   -- local ncpus = node.num_processors
   local ncpus = node.csbase_num_processors
   -- local mem = CNF_LIBRARY[ node.platform_os ].getmem(node)
   local mem = CNF_LIBRARY[PLATFORM].getmem(node)
   -- local border = node.byte_order
   -- return ncpus, mem, border
   return ncpus, mem
end

-- ......................................................................
-- Comandos para aquisição dos tempos finais de execução

PATTERNS.execute_command = function( cmd )
  local str = [[/bin/ksh -c "]]..
              [[/usr/bin/time -p 2> ]]..cmd.time_file..[[ ]]..
              [[/bin/ksh -c ']]..cmd.command..[['"]]
  return str
end

PATTERNS.execute_remote_command = function(cmd)
   local command = string.gsub(cmd.command, '(")','\\"')
   local host= cmd.host
   -- @TODO Rever o uso de SGAD_CONF
   local path = cmd.path or SGAD_CONF.path   -- XXX
   if path then
    -- @TODO Rever o uso de SGAD_CONF
      local relpath, isrelpath = string.gsub(path, "("..SGAD_CONF.home..")","",1) -- XXX
      if isrelpath ~= 0 then
         path = "$HOME/" .. relpath
      end
      path = "cd "..path.." && "
   else
      path = ""
   end
   local sshcmd =[[%s %s "/bin/ksh -c \". /etc/profile;%s %s\" " ]]
   sshcmd = string.format(sshcmd,
                   CNF_LIBRARY.remote_shell,
                   host,   path, command)
  local str = [[/bin/ksh -c ']]..
              [[/usr/bin/time -p 2> ]]..cmd.time_file..[[ ]].. sshcmd .. [[']]
  return str
end

PATTERNS.time_command_function = function( str )
  -- 0.01user 0.00system 0:00.00elapsed
  local values = {}
  string.gsub( str,
    "(.*)[Rr]eal%s*(%S+%d)%D.*[Uu]ser%s*(%S+%d)%D.*[Ss]yst?e?m?%s*(%S+%d)%D.*",
    function( output, r, u, s )
       r = tonumber(r)
       u = tonumber(u)
       s = tonumber(s)
       values.real = r
       values.user = u
       values.system = s
       values.output = output
    end )
  return values.real, values.user, values.system, values.output or str
end

-- ......................................................................
-- comandos para aquisição dos estados dos processos

PATTERNS.processes_command = "ps -eo"
PATTERNS.processes_skip_lines = 1

PATTERNS.init = function(self, platform)
  PLATFORM = platform
  if not CNF_LIBRARY[PLATFORM] then
    servermanager.writeError("Plataforma não cadastrada: ["..PLATFORM.."]")
    os.exit()
  end
  self.processes_formats = CNF_LIBRARY[PLATFORM].processes_formats
  PATTERNS.processes_command = CNF_LIBRARY[PLATFORM].processes_command or
    PATTERNS.processes_command
  -- Atribui à tabela de patterns a função de coleta de dados de execução
  -- dos algoritmos.
  PATTERNS.collect_process_cpu_info_function = CNF_LIBRARY[PLATFORM].collect_process_cpu_info_function
  PATTERNS.collect_process_io_info_function = CNF_LIBRARY[PLATFORM].collect_process_io_info_function
end

--    PROCESS STATE CODES (Linux24 e 24g3)
--     D   uninterruptible sleep (usually IO)
--     R   runnable (on run queue)
--     S   sleeping
--     T   traced or stopped
--     Z   a defunct ("zombie") process
--
--    S (l) The state of the process: (SunOS 58)
--     O     Process is running on a processor.
--     S     Sleeping: process is waiting  for  an  event  to
--           complete.
--     R     Runnable: process is on run queue.
--     Z     Zombie state: process terminated and parent  not
--           waiting.
--     T     Process is stopped, either by a job control sig-
--           nal or because it is being traced.
--
--    For processes: (AIX)
--     O Nonexistent
--     A Active
--     W Swapped
--     I Idle (waiting for startup)
--     Z Canceled
--     T Stopped
--
--    S     (l)      The state of the process: (IRIX)
--     0   Process is running on a processor.
--     S   Process is sleeping, waiting for a resource.
--     R   Process is running.
--     Z   Process is terminated and parent not waiting
--         (wait(2)).
--     T   Process is stopped.
--     I   Process is in intermediate state of creation.
--     X   Process is waiting for memory.
--     C   Process is creating core image after error.
--
--   For Darwin97 processes:
--     state   The state is given by a sequence of letters, for example,
--        ``RWNA''.  The first letter indicates the run state of the
--        process:
--
--        I   Marks a process that is idle (sleeping for longer than
--            about 20 seconds).
--        R   Marks a runnable process.
--        S   Marks a process that is sleeping for less than about 20
--            seconds.
--        T   Marks a stopped process.
--        U   Marks a process in uninterruptible wait.
--        Z   Marks a dead process (a ``zombie'').
--
--        Additional characters after these, if any, indicate
--        additional state information:
--
--        +   The process is in the foreground process group of its
--            control terminal.
--        <   The process has raised CPU scheduling priority.
--        >   The process has specified a soft limit on memory require-
--            ments and is currently exceeding that limit; such a
--            process is (necessarily) not swapped.
--        A   the process has asked for random page replacement
--            (VA_ANOM, from vadvise(2), for example, lisp(1) in a
--            garbage collect).
--        E   The process is trying to exit.
--        L   The process has pages locked in core (for example, for
--            raw I/O).
--        N   The process has reduced CPU scheduling priority (see
--            setpriority(2)).
--        S   The process has asked for FIFO page replacement (VA_SEQL,
--            from vadvise(2), for example, a large image processing
--            program using virtual memory to sequentially address
--            voluminous data).
--        s   The process is a session leader.
--        V   The process is suspended during a vfork.
--        W   The process is swapped out.
--        X   The process is being traced or debugged.


PATTERNS.process_interpreter_function = function( tab )
   tab.process_pid = tonumber(tab.process_pid)
   tab.parent_process_pid = tonumber(tab.parent_process_pid)
   tab.command = tostring(tab.command)

   tab.state = string.sub(tab.state,1,1)
   if tab.state == "R" or                     -- XXX Não está bom!
      tab.state == "O" or                     -- XXX Depende das plataformas!
      tab.state == "A" then tab.state = PROCESS_RUNNING
   elseif tab.state == "S" then tab.state = PROCESS_SLEEPING
   elseif tab.state == "D" or
          tab.state == "I" or
          tab.state == "X" or
          tab.state == "W" then tab.state = PROCESS_WAITING
   else tab.state = PROCESS_FINISHED
   end

   tab.processor_id = tostring(tab.processor_id)
   if tab.state == "-" then tab.state = "unique" end

   table.ram_memory_used = tonumber(table.ram_memory_used)
   table.swap_memory_used = nil --0 -- XXX
   table.cpu_percentage = tonumber(table.cpu_percentage)
-- tab.cpu_time = tonumber(tab.cpu_time) or 0    -- ainda é uma string
-- tab.wall_time = tonumber(tab.wall_time) or 0  -- do tipo 00:00:00
   table.user_time = tonumber(table.user_time)
   table.system_time = tonumber(table.system_time)
   table.virtual_memory = tonumber(table.virtual_memory)
   table.bytes_in = tonumber(table.bytes_in)
   table.bytes_out = tonumber(table.bytes_out)
   table.disk_bytes_read = tonumber(table.disk_bytes_read)
   table.disk_bytes_write = tonumber(table.disk_bytes_write)
end

-- ......................................................................
-- comandos para aquisição da carga e memória utilizada da máquina

CNF = {}

function CNF:pattern_function( sdata, comm, lpatt, mpatt )
  local fname = os.tmpname()
  --local csh_command = 'csh -c "'..comm..' >! '..fname..'"'
  local csh_command = comm..'|head -n15 > '..fname
  servermanager.writeMsg("Executando coleta com ["..csh_command.."]")

  os.execute( csh_command )

  local fd = io.open(fname, "r")
  if not fd then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  local str = fd:read("*a")
  fd:close()

  if not str then
     servermanager.writeError("Falha na leitura do arquivo temporário. ["..fname.."]")
     return
  end
  str = string.gsub( str, "%c", "" )

  os.remove(fname)

  local str_aux = string.gsub( str, lpatt, "%1 %2 %3" )
  str_aux = string.gsub( str_aux, ",", "." )
  local load1 = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
  local load5 = string.gsub( str_aux, "(%S+)%s+(%S+)%s+.*", "%2" )
  local load15 = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+).*", "%3" )

  str_aux = string.gsub( str, mpatt, "%1 %2 %3 %4" )
  local ram = string.gsub( str_aux, "(%S+)%s+.*", "%1" )
  local uram = string.gsub( str_aux, "(%S+)%s+(%S+)%s.*", "%2" )
  local swap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s.*", "%3" )
  local uswap = string.gsub( str_aux, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+).*", "%4" )

  return load1, load5, load15, ram, uram, swap, uswap
end

-- ......................................................................

function CNF:MemValueToMb(value,unit)
  if not unit then -- Byte
    return value / (1024^2)
  elseif unit == "G" or unit == "g" then
    return value * 1024
  elseif unit == "K" or unit == "k" then
    return value / 1024
  else
    return value
  end
end

-- ......................................................................

function CNF:MemValueToBytes(value,unit)
  if unit == "G" or unit == "g" then
    return value * (1024^3)
  elseif unit == "M" or unit == "m" then
    return value * (1024^2)
  elseif unit == "K" or unit == "k" then
    return value * 1024
  else
    return value
  end
end

