ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
ilSessionStatistics Class Reference
+ Collaboration diagram for ilSessionStatistics:

Static Public Member Functions

static isActive ()
 Is session statistics active at all? More...
 
static createRawEntry ($a_session_id, $a_session_type, $a_timestamp, $a_user_id)
 Create raw data entry. More...
 
static closeRawEntry ($a_session_id, $a_context=null, $a_expired_at=null)
 Close raw data entry. More...
 
static aggretateRaw ($a_now)
 Aggregate raw session data (older than given time) More...
 
static aggregateRawHelper ($a_begin, $a_end)
 Aggregate statistics data for one slot. More...
 
static getLastMaxedOut ()
 Get latest slot during which sessions were maxed out. More...
 
static getMaxedOutDuration ($a_from, $a_to)
 Get maxed out duration in given timeframe. More...
 
static getNumberOfSessionsByType ($a_from, $a_to)
 Get session counters by type (opened, closed) More...
 
static getActiveSessions ($a_from, $a_to)
 Get active sessions aggregated data. More...
 
static getLastAggregation ()
 Get timestamp of last aggregation. More...
 
static getLimitForSlot ($a_timestamp)
 Get max session setting for given timestamp. More...
 
static updateLimitLog ($a_new_value)
 Log max session setting. More...
 

Data Fields

const SLOT_SIZE = 15
 

Static Protected Member Functions

static getCurrentSlot ($a_now)
 Get next slot to aggregate. More...
 
static getNumberOfActiveRawSessions ($a_time)
 Count number of active sessions at given time. More...
 
static getRawData ($a_begin, $a_end)
 Read raw data for timespan. More...
 
static createNewAggregationSlot ($a_now)
 Create new slot (using table lock) More...
 
static deleteAggregatedRaw ($a_now)
 Remove already aggregated raw data. More...
 

Detailed Description

Author
Jörg Lützenkirchen luetz.nosp@m.enki.nosp@m.rchen.nosp@m.@lei.nosp@m.fos.c.nosp@m.om
Version
$Id$

Definition at line 11 of file class.ilSessionStatistics.php.

Member Function Documentation

◆ aggregateRawHelper()

static ilSessionStatistics::aggregateRawHelper (   $a_begin,
  $a_end 
)
static

Aggregate statistics data for one slot.

Parameters
timestamp$a_begin
timestamp$a_end

Definition at line 290 of file class.ilSessionStatistics.php.

References $ilDB, $ilSetting, array, ilSession\SESSION_CLOSE_EXPIRE, ilSession\SESSION_CLOSE_FIRST, ilSession\SESSION_CLOSE_IDLE, ilSession\SESSION_CLOSE_LIMIT, ilSession\SESSION_CLOSE_LOGIN, and ilSession\SESSION_CLOSE_USER.

291  {
292  global $ilDB, $ilSetting;
293 
294  // "relevant" closing types
295  $separate_closed = array(ilSession::SESSION_CLOSE_USER,
301 
302  // gather/process data (build event timeline)
303  $closed_counter = $events = array();
304  $opened_counter = 0;
305  foreach(self::getRawData($a_begin, $a_end) as $item)
306  {
307  // open/close counters are _not_ time related
308 
309  // we could filter for undefined/invalid closing contexts
310  // and ignore those items, but this would make any debugging
311  // close to impossible
312  // "closed_other" would have been a good idea...
313 
314  // session opened
315  if($item["start_time"] >= $a_begin)
316  {
317  $opened_counter++;
318  $events[$item["start_time"]][] = 1;
319  }
320  // session closed
321  if($item["end_time"] && $item["end_time"] <= $a_end)
322  {
323  if(in_array($item["end_context"], $separate_closed))
324  {
325  $closed_counter[$item["end_context"]]++;
326  }
327  else
328  {
329  $closed_counter[0]++;
330  }
331  $events[$item["end_time"]][] = -1;
332  }
333  }
334 
335  // initialising active statistical values
336  $active_begin = self::getNumberOfActiveRawSessions($a_begin-1);
337  $active_end = $active_min = $active_max = $active_avg = $active_begin;
338 
339  // parsing events / building avergages
340  if(sizeof($events))
341  {
342  $last_update_avg = $a_begin-1;
343  $slot_seconds = self::SLOT_SIZE*60;
344  $active_avg = 0;
345 
346  // parse all open/closing events
347  ksort($events);
348  foreach($events as $ts => $actions)
349  {
350  // actions which occur in the same second are "merged"
351  foreach($actions as $action)
352  {
353  // max
354  if($action > 0)
355  {
356  $active_end++;
357  }
358  // min
359  else
360  {
361  $active_end--;
362  }
363  }
364 
365  // max
366  if($active_end > $active_max)
367  {
368  $active_max = $active_end;
369  }
370 
371  // min
372  if($active_end < $active_min)
373  {
374  $active_min = $active_end;
375  }
376 
377  // avg
378  $diff = $ts-$last_update_avg;
379  $active_avg += $diff/$slot_seconds*$active_end;
380  $last_update_avg = $ts;
381  }
382  unset($actions);
383 
384  // add up to end of slot if needed
385  if($last_update_avg < $a_end)
386  {
387  $diff = $a_end-$last_update_avg;
388  $active_avg += $diff/$slot_seconds*$active_end;
389  }
390 
391  $active_avg = round($active_avg);
392  }
393  unset($events);
394 
395 
396  // do we (really) need a log here?
397  // $max_sessions = (int)$ilSetting->get("session_max_count", ilSessionControl::DEFAULT_MAX_COUNT);
398  $max_sessions = self::getLimitForSlot($a_begin);
399 
400  // save aggregated data
401  $fields = array(
402  "active_min" => array("integer", $active_min),
403  "active_max" => array("integer", $active_max),
404  "active_avg" => array("integer", $active_avg),
405  "active_end" => array("integer", $active_end),
406  "opened" => array("integer", $opened_counter),
407  "closed_manual" => array("integer", (int)$closed_counter[ilSession::SESSION_CLOSE_USER]),
408  "closed_expire" => array("integer", (int)$closed_counter[ilSession::SESSION_CLOSE_EXPIRE]),
409  "closed_idle" => array("integer", (int)$closed_counter[ilSession::SESSION_CLOSE_IDLE]),
410  "closed_idle_first" => array("integer", (int)$closed_counter[ilSession::SESSION_CLOSE_FIRST]),
411  "closed_limit" => array("integer", (int)$closed_counter[ilSession::SESSION_CLOSE_LIMIT]),
412  "closed_login" => array("integer", (int)$closed_counter[ilSession::SESSION_CLOSE_LOGIN]),
413  "closed_misc" => array("integer", (int)$closed_counter[0]),
414  "max_sessions" => array("integer", (int)$max_sessions)
415  );
416  $ilDB->update("usr_session_stats", $fields,
417  array("slot_begin" => array("integer", $a_begin),
418  "slot_end" => array("integer", $a_end)));
419  }
const SESSION_CLOSE_IDLE
const SESSION_CLOSE_LOGIN
const SESSION_CLOSE_EXPIRE
const SESSION_CLOSE_USER
const SESSION_CLOSE_LIMIT
Create styles array
The data for the language used.
global $ilSetting
Definition: privfeed.php:17
global $ilDB
const SESSION_CLOSE_FIRST

◆ aggretateRaw()

static ilSessionStatistics::aggretateRaw (   $a_now)
static

Aggregate raw session data (older than given time)

Parameters
integer$a_now

Definition at line 266 of file class.ilSessionStatistics.php.

Referenced by ilSession\_writeData(), and ilSessionStatisticsGUI\adminSync().

267  {
268  if(!self::isActive())
269  {
270  return;
271  }
272 
273  $slot = self::createNewAggregationSlot($a_now);
274  while(is_array($slot))
275  {
276  self::aggregateRawHelper($slot[0], $slot[1]);
277  $slot = self::createNewAggregationSlot($a_now);
278  }
279 
280  // #12728
281  self::deleteAggregatedRaw($a_now);
282  }
+ Here is the caller graph for this function:

◆ closeRawEntry()

static ilSessionStatistics::closeRawEntry (   $a_session_id,
  $a_context = null,
  $a_expired_at = null 
)
static

Close raw data entry.

Parameters
int | array$a_session_id
int$a_context
int | bool$a_expired_at

Definition at line 72 of file class.ilSessionStatistics.php.

References $ilDB, and time.

Referenced by ilSession\_destroy().

73  {
74  global $ilDB;
75 
76  if(!self::isActive())
77  {
78  return;
79  }
80 
81  // single entry
82  if(!is_array($a_session_id))
83  {
84  if($a_expired_at)
85  {
86  $end_time = $a_expired_at;
87  }
88  else
89  {
90  $end_time = time();
91  }
92  $sql = "UPDATE usr_session_stats_raw".
93  " SET end_time = ".$ilDB->quote($end_time, "integer");
94  if($a_context)
95  {
96  $sql .= ",end_context = ".$ilDB->quote($a_context, "integer");
97  }
98  $sql .= " WHERE session_id = ".$ilDB->quote($a_session_id, "text").
99  " AND end_time IS NULL";
100  $ilDB->manipulate($sql);
101  }
102  // batch closing
103  else if(!$a_expired_at)
104  {
105  $sql = "UPDATE usr_session_stats_raw".
106  " SET end_time = ".$ilDB->quote(time(), "integer");
107  if($a_context)
108  {
109  $sql .= ",end_context = ".$ilDB->quote($a_context, "integer");
110  }
111  $sql .= " WHERE ".$ilDB->in("session_id", $a_session_id, false, "text").
112  " AND end_time IS NULL";
113  $ilDB->manipulate($sql);
114  }
115  // batch with individual timestamps
116  else
117  {
118  foreach($a_session_id as $id => $ts)
119  {
120  $sql = "UPDATE usr_session_stats_raw".
121  " SET end_time = ".$ilDB->quote($ts, "integer");
122  if($a_context)
123  {
124  $sql .= ",end_context = ".$ilDB->quote($a_context, "integer");
125  }
126  $sql .= " WHERE session_id = ".$ilDB->quote($id, "text").
127  " AND end_time IS NULL";
128  $ilDB->manipulate($sql);
129  }
130  }
131  }
global $ilDB
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ Here is the caller graph for this function:

◆ createNewAggregationSlot()

static ilSessionStatistics::createNewAggregationSlot (   $a_now)
staticprotected

Create new slot (using table lock)

Parameters
integer$a_now
Returns
array begin, end

Definition at line 230 of file class.ilSessionStatistics.php.

References $ilDB, array, and ilDBInterface\insert().

231  {
232  global $ilDB;
233 
234  $ilAtomQuery = $ilDB->buildAtomQuery();
235  $ilAtomQuery->addTableLock("usr_session_stats");
236 
237  $ilAtomQuery->addQueryCallable(function(ilDBInterface $ilDB) use ($a_now, &$slot){
238 
239  // if we had to wait for the lock, no current slot should be returned here
240  $slot = self::getCurrentSlot($a_now);
241  if(!is_array($slot))
242  {
243  $slot = false;
244  return;
245  }
246 
247  // save slot to mark as taken
248  $fields = array(
249  "slot_begin" => array("integer", $slot[0]),
250  "slot_end" => array("integer", $slot[1]),
251  );
252  $ilDB->insert("usr_session_stats", $fields);
253 
254  });
255 
256  $ilAtomQuery->run();
257 
258  return $slot;
259  }
Interface ilDBInterface.
Create styles array
The data for the language used.
global $ilDB
insert($table_name, $values)
+ Here is the call graph for this function:

◆ createRawEntry()

static ilSessionStatistics::createRawEntry (   $a_session_id,
  $a_session_type,
  $a_timestamp,
  $a_user_id 
)
static

Create raw data entry.

Parameters
int$a_session_id
int$a_session_type
int$a_timestamp
int$a_user_id

Definition at line 40 of file class.ilSessionStatistics.php.

References $ilDB, and array.

Referenced by ilSession\_writeData(), and ilSessionControl\checkCurrentSessionIsAllowed().

41  {
42  global $ilDB;
43 
44  if(!$a_user_id || !$a_session_id || !self::isActive())
45  {
46  return;
47  }
48 
49  // #9669: if a session was destroyed and somehow the session id is still
50  // in use there will be a id-collision for the raw-entry
51 
52  $ilDB->replace(
53  "usr_session_stats_raw",
54  array(
55  "session_id" => array("text", $a_session_id)
56  ),
57  array(
58  "type" => array("integer", $a_session_type),
59  "start_time" => array("integer", $a_timestamp),
60  "user_id" => array("integer", $a_user_id)
61  )
62  );
63  }
Create styles array
The data for the language used.
global $ilDB
+ Here is the caller graph for this function:

◆ deleteAggregatedRaw()

static ilSessionStatistics::deleteAggregatedRaw (   $a_now)
staticprotected

Remove already aggregated raw data.

Parameters
integer$a_now

Definition at line 426 of file class.ilSessionStatistics.php.

References $ilDB.

427  {
428  global $ilDB;
429 
430  // we are rather defensive here - 7 days BEFORE current aggregation
431  $cut = $a_now-(60*60*24*7);
432 
433  $ilDB->manipulate("DELETE FROM usr_session_stats_raw".
434  " WHERE start_time <= ".$ilDB->quote($cut, "integer"));
435  }
global $ilDB

◆ getActiveSessions()

static ilSessionStatistics::getActiveSessions (   $a_from,
  $a_to 
)
static

Get active sessions aggregated data.

Parameters
int$a_from
int$a_to
Returns
array

Definition at line 510 of file class.ilSessionStatistics.php.

References $ilDB, $res, $row, and array.

Referenced by ilSessionStatisticsGUI\buildData().

511  {
512  global $ilDB;
513 
514  $sql = "SELECT slot_begin, slot_end, active_min, active_max, active_avg,".
515  " max_sessions".
516  " FROM usr_session_stats".
517  " WHERE slot_end > ".$ilDB->quote($a_from, "integer").
518  " AND slot_begin < ".$ilDB->quote($a_to, "integer").
519  " ORDER BY slot_begin";
520  $res = $ilDB->query($sql);
521  $all = array();
522  while($row = $ilDB->fetchAssoc($res))
523  {
524  $all[] = $row;
525  }
526  return $all;
527  }
Create styles array
The data for the language used.
global $ilDB
+ Here is the caller graph for this function:

◆ getCurrentSlot()

static ilSessionStatistics::getCurrentSlot (   $a_now)
staticprotected

Get next slot to aggregate.

Parameters
integer$a_now
Returns
array begin, end

Definition at line 139 of file class.ilSessionStatistics.php.

References $ilDB, $res, $row, array, and date.

140  {
141  global $ilDB;
142 
143  // get latest slot in db
144  $sql = "SELECT MAX(slot_end) previous_slot_end".
145  " FROM usr_session_stats";
146  $res = $ilDB->query($sql);
147  $row = $ilDB->fetchAssoc($res);
148  $previous_slot_end = $row["previous_slot_end"];
149 
150  // no previous slot? calculate last complete slot
151  // should we use minimum session raw date instead? (problem: table lock)
152  if(!$previous_slot_end)
153  {
154  $slot = floor(date("i")/self::SLOT_SIZE);
155  // last slot of previous hour
156  if(!$slot)
157  {
158  $current_slot_begin = mktime(date("H", $a_now)-1, 60-self::SLOT_SIZE, 0);
159  }
160  // "normalize" to slot
161  else
162  {
163  $current_slot_begin = mktime(date("H", $a_now), ($slot-1)*self::SLOT_SIZE, 0);
164  }
165  }
166  else
167  {
168  $current_slot_begin = $previous_slot_end+1;
169  }
170 
171  $current_slot_end = $current_slot_begin+(60*self::SLOT_SIZE)-1;
172 
173  // no complete slot: nothing to do yet
174  if($current_slot_end < $a_now)
175  {
176  return array($current_slot_begin, $current_slot_end);
177  }
178  }
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
Create styles array
The data for the language used.
global $ilDB

◆ getLastAggregation()

static ilSessionStatistics::getLastAggregation ( )
static

Get timestamp of last aggregation.

Returns
timestamp

Definition at line 534 of file class.ilSessionStatistics.php.

References $ilDB, $res, and $row.

Referenced by ilSessionStatisticsGUI\renderCurrentBasics().

535  {
536  global $ilDB;
537 
538  $sql = "SELECT max(slot_end) latest FROM usr_session_stats";
539  $res = $ilDB->query($sql);
540  $row = $ilDB->fetchAssoc($res);
541  if($row["latest"])
542  {
543  return $row["latest"];
544  }
545  }
global $ilDB
+ Here is the caller graph for this function:

◆ getLastMaxedOut()

static ilSessionStatistics::getLastMaxedOut ( )
static

Get latest slot during which sessions were maxed out.

Returns
int timestamp

Definition at line 442 of file class.ilSessionStatistics.php.

References $ilDB, $res, and $row.

Referenced by ilSessionStatisticsGUI\renderCurrentBasics().

443  {
444  global $ilDB;
445 
446  $sql = "SELECT max(slot_end) latest FROM usr_session_stats".
447  " WHERE active_max >= max_sessions".
448  " AND max_sessions > ".$ilDB->quote(0, "integer");
449  $res = $ilDB->query($sql);
450  $row = $ilDB->fetchAssoc($res);
451  if($row["latest"])
452  {
453  return $row["latest"];
454  }
455  }
global $ilDB
+ Here is the caller graph for this function:

◆ getLimitForSlot()

static ilSessionStatistics::getLimitForSlot (   $a_timestamp)
static

Get max session setting for given timestamp.

Parameters
timestamp$a_timestamp
Returns
int

Definition at line 553 of file class.ilSessionStatistics.php.

References $ilDB, $ilSetting, $res, and ilSessionControl\DEFAULT_MAX_COUNT.

554  {
555  global $ilDB, $ilSetting;
556 
557  $ilDB->setLimit(1);
558  $sql = "SELECT maxval FROM usr_session_log".
559  " WHERE tstamp <= ".$ilDB->quote($a_timestamp, "integer").
560  " ORDER BY tstamp DESC";
561  $res = $ilDB->query($sql);
562  $val = $ilDB->fetchAssoc($res);
563  if($val["maxval"])
564  {
565  return (int)$val["maxval"];
566  }
567  else
568  {
569  return (int)$ilSetting->get("session_max_count", ilSessionControl::DEFAULT_MAX_COUNT);
570  }
571  }
const DEFAULT_MAX_COUNT
default value for settings that have not been defined in setup or administration yet ...
global $ilSetting
Definition: privfeed.php:17
global $ilDB

◆ getMaxedOutDuration()

static ilSessionStatistics::getMaxedOutDuration (   $a_from,
  $a_to 
)
static

Get maxed out duration in given timeframe.

Parameters
int$a_from
int$a_to
Returns
int seconds

Definition at line 464 of file class.ilSessionStatistics.php.

References $ilDB, $res, and $row.

Referenced by ilSessionStatisticsGUI\buildData().

465  {
466  global $ilDB;
467 
468  $sql = "SELECT SUM(slot_end-slot_begin) dur FROM usr_session_stats".
469  " WHERE active_max >= max_sessions".
470  " AND max_sessions > ".$ilDB->quote(0, "integer").
471  " AND slot_end > ".$ilDB->quote($a_from, "integer").
472  " AND slot_begin < ".$ilDB->quote($a_to, "integer");
473  $res = $ilDB->query($sql);
474  $row = $ilDB->fetchAssoc($res);
475  if($row["dur"])
476  {
477  return $row["dur"];
478  }
479  }
global $ilDB
+ Here is the caller graph for this function:

◆ getNumberOfActiveRawSessions()

static ilSessionStatistics::getNumberOfActiveRawSessions (   $a_time)
staticprotected

Count number of active sessions at given time.

Parameters
integer$a_time
Returns
integer

Definition at line 186 of file class.ilSessionStatistics.php.

References $ilDB, $res, $row, and ilSessionControl\$session_types_controlled.

187  {
188  global $ilDB;
189 
190  $sql = "SELECT COUNT(*) counter FROM usr_session_stats_raw".
191  " WHERE (end_time IS NULL OR end_time >= ".$ilDB->quote($a_time, "integer").")".
192  " AND start_time <= ".$ilDB->quote($a_time, "integer").
193  " AND ".$ilDB->in("type", ilSessionControl::$session_types_controlled, false, "integer");
194  $res = $ilDB->query($sql);
195  $row = $ilDB->fetchAssoc($res);
196  return $row["counter"];
197  }
global $ilDB

◆ getNumberOfSessionsByType()

static ilSessionStatistics::getNumberOfSessionsByType (   $a_from,
  $a_to 
)
static

Get session counters by type (opened, closed)

Parameters
int$a_from
int$a_to
Returns
array

Definition at line 488 of file class.ilSessionStatistics.php.

References $ilDB, and $res.

Referenced by ilSessionStatisticsGUI\buildData().

489  {
490  global $ilDB;
491 
492  $sql = "SELECT SUM(opened) opened, SUM(closed_manual) closed_manual,".
493  " SUM(closed_expire) closed_expire, SUM(closed_idle) closed_idle,".
494  " SUM(closed_idle_first) closed_idle_first, SUM(closed_limit) closed_limit,".
495  " SUM(closed_login) closed_login, SUM(closed_misc) closed_misc".
496  " FROM usr_session_stats".
497  " WHERE slot_end > ".$ilDB->quote($a_from, "integer").
498  " AND slot_begin < ".$ilDB->quote($a_to, "integer");
499  $res = $ilDB->query($sql);
500  return $ilDB->fetchAssoc($res);
501  }
global $ilDB
+ Here is the caller graph for this function:

◆ getRawData()

static ilSessionStatistics::getRawData (   $a_begin,
  $a_end 
)
staticprotected

Read raw data for timespan.

Parameters
integer$a_begin
integer$a_end
Returns
array

Definition at line 206 of file class.ilSessionStatistics.php.

References $ilDB, $res, $row, ilSessionControl\$session_types_controlled, and array.

207  {
208  global $ilDB;
209 
210  $sql = "SELECT start_time,end_time,end_context FROM usr_session_stats_raw".
211  " WHERE start_time <= ".$ilDB->quote($a_end, "integer").
212  " AND (end_time IS NULL OR end_time >= ".$ilDB->quote($a_begin, "integer").")".
213  " AND ".$ilDB->in("type", ilSessionControl::$session_types_controlled, false, "integer").
214  " ORDER BY start_time";
215  $res = $ilDB->query($sql);
216  $all = array();
217  while($row = $ilDB->fetchAssoc($res))
218  {
219  $all[] = $row;
220  }
221  return $all;
222  }
Create styles array
The data for the language used.
global $ilDB

◆ isActive()

static ilSessionStatistics::isActive ( )
static

Is session statistics active at all?

Returns
bool

Definition at line 20 of file class.ilSessionStatistics.php.

References $ilSetting.

21  {
22  global $ilSetting;
23 
24  return (bool)$ilSetting->get('session_statistics', 1);
25 
26  /* #13566 - includes somehow won't work this late in the request - doing it directly
27  include_once "Services/Tracking/classes/class.ilObjUserTracking.php";
28  return ilObjUserTracking::_enabledSessionStatistics();
29  */
30  }
global $ilSetting
Definition: privfeed.php:17

◆ updateLimitLog()

static ilSessionStatistics::updateLimitLog (   $a_new_value)
static

Log max session setting.

Parameters
int$a_new_value

Definition at line 578 of file class.ilSessionStatistics.php.

References $ilDB, $ilSetting, $ilUser, array, ilSessionControl\DEFAULT_MAX_COUNT, and time.

Referenced by ilObjUserFolderGUI\saveGeneralSettingsObject().

579  {
580  global $ilDB, $ilSetting, $ilUser;
581 
582  $new_value = (int)$a_new_value;
583  $old_value = (int)$ilSetting->get("session_max_count", ilSessionControl::DEFAULT_MAX_COUNT);
584 
585  if($new_value != $old_value)
586  {
587  $fields = array(
588  "tstamp" => array("timestamp", time()),
589  "maxval" => array("integer", $new_value),
590  "user_id" => array("integer", $ilUser->getId())
591  );
592  $ilDB->insert("usr_session_log", $fields);
593  }
594  }
const DEFAULT_MAX_COUNT
default value for settings that have not been defined in setup or administration yet ...
$ilUser
Definition: imgupload.php:18
Create styles array
The data for the language used.
global $ilSetting
Definition: privfeed.php:17
global $ilDB
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ Here is the caller graph for this function:

Field Documentation

◆ SLOT_SIZE

const ilSessionStatistics::SLOT_SIZE = 15

Definition at line 13 of file class.ilSessionStatistics.php.


The documentation for this class was generated from the following file: