usage_data.F90 8.55 KB
Newer Older
1 2 3 4 5 6
!--------------------------------------------------------------------------------
! Copyright (c) 2016 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
! This file is part of FLEUR and available as free software under the conditions
! of the MIT license as expressed in the LICENSE file in more detail.
!--------------------------------------------------------------------------------
MODULE m_judft_usage
Matthias Redies's avatar
Matthias Redies committed
7 8 9
   IMPLICIT NONE
   PRIVATE
   CHARACTER(LEN=99),PARAMETER:: URL_STRING="www.flapw.de/collect.pl"
10
   INTEGER,PARAMETER :: MAX_NO_KEYS=40
Matthias Redies's avatar
Matthias Redies committed
11 12 13
   CHARACTER(LEN=200) :: keys(MAX_NO_KEYS)
   CHARACTER(LEN=200) :: values(MAX_NO_KEYS)
   INTEGER           :: no_keys=0
14

Matthias Redies's avatar
Matthias Redies committed
15
   INTERFACE add_usage_data
Matthias Redies's avatar
Matthias Redies committed
16
      MODULE PROCEDURE  add_usage_data_s,add_usage_data_i,add_usage_data_l,add_usage_data_r
Matthias Redies's avatar
Matthias Redies committed
17 18 19
   END INTERFACE add_usage_data

   PUBLIC :: add_usage_data,send_usage_data
20 21

CONTAINS
Matthias Redies's avatar
Matthias Redies committed
22 23
   SUBROUTINE add_usage_data_s(key,VALUE,string_val)
      use m_juDFT_string
Matthias Redies's avatar
Matthias Redies committed
24
      IMPLICIT NONE
25 26
      CHARACTER(len=*),INTENT(IN)  :: key,VALUE
      INTEGER                      :: i
Matthias Redies's avatar
Matthias Redies committed
27 28 29 30 31 32 33 34
      LOGICAL, OPTIONAL            :: string_val
      LOGICAL                      :: add_quotes

      IF(PRESENT(string_val)) THEN
         add_quotes = string_val
      ELSE
         add_quotes = .True.
      ENDIF
35 36 37 38 39 40

      ! don't add a key twice
      do i = 1,no_keys
         if(keys(i) == key) return
      enddo

Matthias Redies's avatar
Matthias Redies committed
41 42
      no_keys=no_keys+1
      IF (no_keys>MAX_NO_KEYS) STOP "BUG, too many keys in usage_data"
Matthias Redies's avatar
Matthias Redies committed
43 44 45 46 47 48 49
      keys(no_keys) = key
      
      IF(add_quotes) THEN
         values(no_keys) = '"' // strip(VALUE) // '"'
      ELSE
         values(no_keys) = VALUE
      ENDIF
Matthias Redies's avatar
Matthias Redies committed
50 51 52 53 54 55 56
   END SUBROUTINE add_usage_data_s

   SUBROUTINE add_usage_data_i(key,VALUE)
      IMPLICIT NONE
      CHARACTER(len=*),INTENT(IN):: key
      INTEGER,intent(in)         :: value
      CHARACTER(len=20)::txt
Matthias Redies's avatar
Matthias Redies committed
57

Matthias Redies's avatar
Matthias Redies committed
58
      WRITE(txt,*) VALUE
Matthias Redies's avatar
Matthias Redies committed
59
      CALL add_usage_data_s(key,txt, string_val=.False.)
Matthias Redies's avatar
Matthias Redies committed
60
   END SUBROUTINE add_usage_data_i
Matthias Redies's avatar
Matthias Redies committed
61 62 63 64 65 66 67 68
   
   SUBROUTINE add_usage_data_r(key,VALUE)
      IMPLICIT NONE
      CHARACTER(len=*),INTENT(IN):: key
      REAL,intent(in)            :: value

      CHARACTER(len=20)::txt
      WRITE(txt,'(F18.2)') VALUE
Matthias Redies's avatar
Matthias Redies committed
69
      CALL add_usage_data_s(key,txt, string_val=.False.)
Matthias Redies's avatar
Matthias Redies committed
70
   END SUBROUTINE add_usage_data_r
71

Matthias Redies's avatar
Matthias Redies committed
72 73 74 75
   SUBROUTINE add_usage_data_l(key,VALUE)
      IMPLICIT NONE
      CHARACTER(len=*),INTENT(IN):: key
      LOGICAL,INTENT(in)         :: VALUE
76

Matthias Redies's avatar
Matthias Redies committed
77
      CHARACTER(len=20)::txt
78
      txt=MERGE("true ","false",value)
Matthias Redies's avatar
Matthias Redies committed
79
      CALL add_usage_data_s(key,txt, string_val=.False.)
Matthias Redies's avatar
Matthias Redies committed
80
   END SUBROUTINE add_usage_data_l
81

Matthias Redies's avatar
Matthias Redies committed
82
   SUBROUTINE send_usage_data()
83
      use m_juDFT_args
Matthias Redies's avatar
Matthias Redies committed
84
      use m_juDFT_string
Matthias Redies's avatar
Matthias Redies committed
85
      IMPLICIT NONE
Matthias Redies's avatar
Matthias Redies committed
86
      INTEGER            :: i,ierr(2),pid,dt(8)
87
      CHARACTER(len=200) :: model, modelname, VmPeak, VmSize, VmData, VmStk, VmExe, VmSwap
Matthias Redies's avatar
Matthias Redies committed
88
      INTEGER(8)         :: r
89
#ifdef CPP_MPI
Matthias Redies's avatar
Matthias Redies committed
90
      INCLUDE 'mpif.h'
91
      LOGICAL MPI_init
92
      CALL MPI_INITIALIZED(mpi_init,ierr)
93 94 95 96
      IF (mpi_init) THEN
         CALL MPI_COMM_RANK(MPI_COMM_WORLD,i,ierr)
         IF (i.NE.0) RETURN
      ENDIF
97 98 99
#endif

!#ifdef CPP_ALLOW_USAGE_DATA
100
      r = random_id()
101 102

      !add cpuinfos
Matthias Redies's avatar
Matthias Redies committed
103 104 105
      call get_cpuinfo(model, modelname)
      call add_usage_data("cpu_model", model)
      call add_usage_data("cpu_modelname", modelname)
Matthias Redies's avatar
Matthias Redies committed
106

107 108
      !add meminfos
      call get_meminfo(VmPeak, VmSize, VmData, VmStk, VmExe, VmSwap)
Matthias Redies's avatar
Matthias Redies committed
109 110 111 112 113 114
      call add_usage_data("VmPeak", VmPeak, string_val=.False.)
      call add_usage_data("VmSize", VmSize, string_val=.False.)
      call add_usage_data("VmData", VmData, string_val=.False.)
      call add_usage_data("VmStk",  VmStk, string_val=.False.)
      call add_usage_data("VmExe",  VmExe, string_val=.False.)
      call add_usage_data("VmSwap", VmSwap, string_val=.False.)
115

Matthias Redies's avatar
Matthias Redies committed
116 117
      !First write a json file
      OPEN(unit=961,file="usage.json",status='replace')
118
      WRITE(961,'(A)') '{'
Matthias Redies's avatar
Matthias Redies committed
119
      WRITE(961,*) '  "url":"',strip(URL_STRING),'",'
120
      WRITE(961,"(a,Z0.16,a)") '   "calculation-id":"',r,'",'
Matthias Redies's avatar
Matthias Redies committed
121 122
      WRITE(961,*) '  "data": {'
      DO i=1,no_keys
123 124 125 126 127
         if(i < no_keys) then
            WRITE(961,*) '       "',strip(keys(i)),'":',strip(values(i)),","
         else
            WRITE(961,*) '       "',strip(keys(i)),'":',strip(values(i))
         endif
Matthias Redies's avatar
Matthias Redies committed
128 129
      ENDDO
      WRITE(961,*) '     }'
130
      WRITE(961,"(A)") '}'
Matthias Redies's avatar
Matthias Redies committed
131
      CLOSE(961)
132

Matthias Redies's avatar
Matthias Redies committed
133 134 135
      IF (judft_was_argument("-no_send")) THEN
         PRINT *,"As requested by command line option usage data was not send, please send usage.json manually"
      ELSE
136 137 138
#ifdef CPP_DEBUG
         WRITE (*,*) "usage.json not send, because this is a debugging run."
#else
Daniel Wortmann's avatar
Daniel Wortmann committed
139
#ifdef  __INTEL_COMPILER
Matthias Redies's avatar
Matthias Redies committed
140
         !Send using curl
141
         call execute_command_line(&
Matthias Redies's avatar
Matthias Redies committed
142
            'curl --output /dev/null -m 5 -X POST -H "Content-Type: application/json" -d @usage.json https://docker.iff.kfa-juelich.de/fleur-usage-stats/',&
Matthias Redies's avatar
Matthias Redies committed
143
            exitstat=ierr(1), cmdstat=ierr(2))
Daniel Wortmann's avatar
Daniel Wortmann committed
144
         IF(ALL(ierr == 0)) THEN
145 146 147
            write (*,*) "Usage data send using curl: usage.json"
         else
            write (*,*) "Usage data sending failed"
Daniel Wortmann's avatar
Daniel Wortmann committed
148 149 150 151
         ENDIF
#else
         CALL system('curl --output /dev/null -m 5 -X POST -H "Content-Type: application/json" -d @usage.json https://docker.iff.kfa-juelich.de/fleur-usage-stats/')
#endif         
152

153
#endif
154
      ENDIF
155 156 157
!#else
!    PRINT *,"No usage data collected"
!#endif
Matthias Redies's avatar
Matthias Redies committed
158
   END SUBROUTINE send_usage_data
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

   FUNCTION random_id() result(r)
      implicit none
      integer(8)     :: r, rand_i
      integer        :: dt(8), i
      real(8)       :: rand_r

      CALL DATE_AND_TIME(values = dt)
      r = (dt(1) - 1970) * 365 * 24 * 60 * 60 * 1000 + &
          dt(2) * 31 * 24 * 60 * 60 * 1000 + &
          dt(3) * 24 * 60 * 60  * 1000 + dt(5) * 60 * 60 * 1000 + &
          dt(6) * 60 * 1000 + dt(7) * 1000 + dt(8)

      ! 10 times xorshift64
      do i = 1,10
         r = ieor(r, ishft(r,13))
         r = ieor(r, ishft(r,-7))
         r = ieor(r, ishft(r,17))
      enddo
   END FUNCTION random_id
Matthias Redies's avatar
Matthias Redies committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

   SUBROUTINE get_cpuinfo(model, modelname)
      implicit none
      character(len=200), intent(out) :: model, modelname
      character(len=1000)             :: line
      integer                         :: openstatus, readstatus
      logical                         :: found_model, found_modelname, done

      model     = "unknown"
      modelname = "unknown"

      done            = .False.
      found_model     = .False.
      found_modelname = .False.

      readstatus      = 0

      open(unit=77, file="/proc/cpuinfo", iostat=openstatus)
      if(openstatus == 0) then
         do while(.not. done)
            read(77,'(A)', iostat=readstatus) line

            if(readstatus == 0) then
               if(index(line, "model name") /= 0) then
                  modelname = trim(line(index(line, ":")+1:1000))

                  found_modelname = .True.
                  done            = found_modelname .and. found_model
                  cycle
               endif
               
               if(index(line, "model") /= 0) then
                  model = trim(line(index(line,":")+1:1000))

                  found_model = .True.
                  done        = found_modelname .and. found_model
                  cycle
               endif
            else
               exit
            endif
         enddo
      endif
      if(openstatus == 0) close(77)
   END SUBROUTINE get_cpuinfo

225 226 227 228 229 230
   SUBROUTINE get_meminfo(VmPeak, VmSize, VmData, VmStk, VmExe, VmSwap)
      use m_juDFT_string
      implicit none
      character(len=200), intent(out)   :: VmPeak, VmSize, VmData, VmStk, VmExe, VmSwap
      character(len=1000)               :: line
      integer                           :: openstat, readstat
Matthias Redies's avatar
Matthias Redies committed
231 232

   
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
      VmPeak = ""
      VmSize = ""
      VmData = ""
      VmStk  = ""
      VmExe  = ""
      VmSwap = ""

      readstat = 0

      open(unit=77, file="/proc/self/status", iostat=openstat)
      do while(readstat == 0)
         read(77,'(A)', iostat=readstat) line
         if(index(line, "VmPeak") /= 0) VmPeak = strip(line(index(line, ":")+1:index(line,"kB", back=.True.)-1))
         if(index(line, "VmSize") /= 0) VmSize = strip(line(index(line, ":")+1:index(line,"kB", back=.True.)-1))
         if(index(line, "VmData") /= 0) VmData = strip(line(index(line, ":")+1:index(line,"kB", back=.True.)-1))
         if(index(line, "VmStk")  /= 0) VmStk  = strip(line(index(line, ":")+1:index(line,"kB", back=.True.)-1))
         if(index(line, "VmExe")  /= 0) VmExe  = strip(line(index(line, ":")+1:index(line,"kB", back=.True.)-1))
         if(index(line, "VmSwap") /= 0) VmSwap = strip(line(index(line, ":")+1:index(line,"kB", back=.True.)-1))
      enddo

      if(openstat == 0) close(77)

   END SUBROUTINE
Matthias Redies's avatar
Matthias Redies committed
256

257
END MODULE m_judft_usage