From dd4d35928cca5aee719b92e9f414a74a9fbe769e Mon Sep 17 00:00:00 2001 From: acanas Date: Fri, 1 May 2020 19:15:59 +0200 Subject: [PATCH] Version19.208 --- Makefile | 6 +-- sql/swad.sql | 10 ++++ swad_changelog.h | 8 ++- swad_database.c | 19 +++++-- swad_figure.c | 13 ----- swad_figure_cache.c | 123 +++++++++++++++++++++++++++++++++++++++++++ swad_figure_cache.h | 67 +++++++++++++++++++++++ swad_system_config.c | 88 +++++++++++++++++++++++++++---- 8 files changed, 302 insertions(+), 32 deletions(-) create mode 100644 swad_figure_cache.c create mode 100644 swad_figure_cache.h diff --git a/Makefile b/Makefile index cf232d28..de6eb94f 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,9 @@ OBJS = swad_account.o swad_action.o swad_agenda.o swad_alert.o \ swad_degree_type.o swad_department.o swad_duplicate.o \ swad_enrolment.o swad_exam.o swad_exam_announcement.o \ swad_exam_event.o swad_exam_result.o \ - swad_figure.o swad_file.o swad_file_browser.o swad_file_extension.o \ - swad_file_MIME.o swad_firewall.o swad_follow.o swad_form.o \ - swad_forum.o \ + swad_figure.o swad_figure_cache.o swad_file.o swad_file_browser.o \ + swad_file_extension.o swad_file_MIME.o swad_firewall.o swad_follow.o \ + swad_form.o swad_forum.o \ swad_game.o swad_global.o swad_group.o \ swad_help.o swad_hierarchy.o swad_hierarchy_config.o swad_holiday.o \ swad_HTML.o \ diff --git a/sql/swad.sql b/sql/swad.sql index d9ee90cf..a3156176 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -598,6 +598,16 @@ CREATE TABLE IF NOT EXISTS expanded_folders ( INDEX(FileBrowser,Cod), INDEX(WorksUsrCod)); -- +-- Table figures: stores cached figures for quick retrieval of figures (i.e. number of students in the platform) +-- +CREATE TABLE IF NOT EXISTS figures ( + Figure INT NOT NULL, + Scope ENUM('Sys','Cty','Ins','Ctr','Deg','Crs') NOT NULL DEFAULT 'Sys', + Cod INT NOT NULL DEFAULT -1, + Value INT NOT NULL, + LastUpdate TIMESTAMP, + UNIQUE INDEX(Figure,Scope,Cod)); +-- -- Table file_browser_last: stores the last click of every user in each file browser zone -- CREATE TABLE IF NOT EXISTS file_browser_last ( diff --git a/swad_changelog.h b/swad_changelog.h index c35a39d8..f5954185 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -544,10 +544,16 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.207.4 (2020-04-30)" +#define Log_PLATFORM_VERSION "SWAD 19.208 (2020-05-01)" #define CSS_FILE "swad19.193.1.css" #define JS_FILE "swad19.193.1.js" /* + Version 19.208: May 01, 2020 Optimization in table of last prefs on user-course. (300598 lines) + 1 change necessary in database: +CREATE TABLE IF NOT EXISTS figures (Figure INT NOT NULL,Scope ENUM('Sys','Cty','Ins','Ctr','Deg','Crs') NOT NULL DEFAULT 'Sys',Cod INT NOT NULL DEFAULT -1,Value INT NOT NULL,LastUpdate TIMESTAMP,UNIQUE INDEX(Figure,Scope,Cod)); + If you want to use MyISAM: +ALTER TABLE figures ENGINE=MyISAM; + Version 19.207.4: Apr 30, 2020 Fixed bug in test result, reported by Mancia Anguita López. (300363 lines) Version 19.207.3: Apr 30, 2020 Fixed bug removing account. (300335 lines) Version 19.207.2: Apr 30, 2020 Fixed bug creating account, reported by Antonio Becerra. (300334 lines) diff --git a/swad_database.c b/swad_database.c index 7df70036..6a4dd937 100644 --- a/swad_database.c +++ b/swad_database.c @@ -1317,13 +1317,24 @@ mysql> DESCRIBE expanded_folders; /***** Table figures *****/ /* mysql> DESCRIBE figures; - ++------------+-------------------------------------------+------+-----+-------------------+-----------------------------+ +| Field | Type | Null | Key | Default | Extra | ++------------+-------------------------------------------+------+-----+-------------------+-----------------------------+ +| Figure | int(11) | NO | PRI | NULL | | +| Scope | enum('Sys','Cty','Ins','Ctr','Deg','Crs') | NO | PRI | Sys | | +| Cod | int(11) | NO | PRI | -1 | | +| Value | int(11) | NO | | NULL | | +| LastUpdate | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | ++------------+-------------------------------------------+------+-----+-------------------+-----------------------------+ +5 rows in set (0.01 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS figures (" - "Name VARCHAR(32) NOT NULL," // Fig_MAX_BYTES_NAME + "Figure INT NOT NULL," + "Scope ENUM('Sys','Cty','Ins','Ctr','Deg','Crs') NOT NULL DEFAULT 'Sys'," + "Cod INT NOT NULL DEFAULT -1," "Value INT NOT NULL," - "CalcTime DATETIME NOT NULL," - "UNIQUE INDEX(Name))"); + "LastUpdate TIMESTAMP," + "UNIQUE INDEX(Figure,Scope,Cod))"); /***** Table file_browser_last *****/ /* diff --git a/swad_figure.c b/swad_figure.c index b4bef0e0..32490e05 100644 --- a/swad_figure.c +++ b/swad_figure.c @@ -65,8 +65,6 @@ extern struct Globals Gbl; /***************************** Private constants *****************************/ /*****************************************************************************/ -#define Fig_MAX_BYTES_NAME 32 - /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ @@ -197,7 +195,6 @@ static void Fig_GetAndShowNumUsrsPerMenu (void); static void Fig_GetAndShowNumUsrsPerTheme (void); static void Fig_GetAndShowNumUsrsPerSideColumns (void); unsigned Fig_GetNumUsrsWhoChoseAnOption (const char *SubQuery); -bool Fig_GetFigureFromCache (const char *Name); /*****************************************************************************/ /************************** Show use of the platform *************************/ @@ -5675,13 +5672,3 @@ unsigned Fig_GetNumUsrsWhoChoseAnOption (const char *SubQuery) return NumUsrs; } - -/*****************************************************************************/ -/************** Get number of users who have chosen an option ****************/ -/*****************************************************************************/ -// Return true is figure is valid (if figure is cached and recently calculated) - -bool Fig_GetFigureFromCache (const char *Name) - { - return Name[0] ? true : false; - } diff --git a/swad_figure_cache.c b/swad_figure_cache.c new file mode 100644 index 00000000..ba8d6bbe --- /dev/null +++ b/swad_figure_cache.c @@ -0,0 +1,123 @@ +// swad_figure_cache.c: figures (global stats) cached in database + +/* + SWAD (Shared Workspace At a Distance), + is a web platform developed at the University of Granada (Spain), + and used to support university teaching. + + This file is part of SWAD core. + Copyright (C) 1999-2020 Antonio Cañas Vargas + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ +/*****************************************************************************/ +/********************************* Headers ***********************************/ +/*****************************************************************************/ + +//#define _GNU_SOURCE // For asprintf +#include // For sscanf +//#include // For system, getenv, etc. +//#include // For string functions + +#include "swad_database.h" +#include "swad_figure_cache.h" +#include "swad_scope.h" + +/*****************************************************************************/ +/************** External global variables from others modules ****************/ +/*****************************************************************************/ + +// extern struct Globals Gbl; + +/*****************************************************************************/ +/***************************** Private constants *****************************/ +/*****************************************************************************/ + +#define FigCch_TIME_CACHE ((time_t)(1UL * 60UL * 60UL)) // Past these seconds, update cached value + +/*****************************************************************************/ +/******************************* Private types *******************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/***************************** Private variables *****************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/****************************** Private prototypes ***************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/************** Get number of users who have chosen an option ****************/ +/*****************************************************************************/ + +void FigCch_UpdateFigureIntoCache (FigCch_FigureCached_t Figure, + Hie_Level_t Scope,long Cod, + unsigned Value) + { + /***** Trivial check *****/ + if (Figure == FigCch_UNKNOWN) + return; + + /***** Update figure's value in database *****/ + DB_QueryREPLACE ("can not update cached figure value", + "REPLACE INTO figures" + " (Figure,Scope,Cod,Value)" + " VALUES" + " (%u,'%s',%ld,%u)", + (unsigned) Figure,Sco_GetDBStrFromScope (Scope),Cod,Value); + } + +/*****************************************************************************/ +/************** Get number of users who have chosen an option ****************/ +/*****************************************************************************/ +// Return true is figure is found (if figure is cached and recently updated) + +bool FigCch_GetFigureFromCache (FigCch_FigureCached_t Figure, + Hie_Level_t Scope,long Cod, + unsigned *Value) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + bool Found = false; + + *Value = 0; // Default value when not found + + /***** Trivial check *****/ + if (Figure == FigCch_UNKNOWN) + return Found; + + /***** Get figure's value if cached and recent *****/ + if (DB_QuerySELECT (&mysql_res,"can not get cached figure value", + "SELECT Value" + " FROM figures" + " WHERE Figure=%u AND Scope='%s' AND Cod=%ld" + " AND LastUpdate. +*/ +/*****************************************************************************/ +/********************************* Headers ***********************************/ +/*****************************************************************************/ + +#include // For boolean type + +#include "swad_hierarchy.h" + +/*****************************************************************************/ +/************************** Public types and constants ***********************/ +/*****************************************************************************/ + +// If numbers change, clean database table figures: "DELETE FROM figures;" +typedef enum + { + FigCch_UNKNOWN = 0, // Unknown figure + //-------------------------------------------------------------------------- + FigCch_NUM_STDS_IN_CRSS = 1, // Number of students in courses + FigCch_NUM_NETS_IN_CRSS = 2, // Number of non-editing teachers in courses + FigCch_NUM_TCHS_IN_CRSS = 3, // Number of teachers in courses + FigCch_NUM_USRS_IN_CRSS = 4, // Number of users in courses + //-------------------------------------------------------------------------- + FigCch_NUM_CTYS = 5, // Number of countries + FigCch_NUM_INSS = 6, // Number of institutions + FigCch_NUM_CTRS = 7, // Number of centres + FigCch_NUM_CTRS_WITH_MAP = 8, // Number of centres with map + FigCch_NUM_DEGS = 9, // Number of degrees + FigCch_NUM_CRSS = 10, // Number of courses + } FigCch_FigureCached_t; + +/*****************************************************************************/ +/***************************** Public prototypes *****************************/ +/*****************************************************************************/ + +void FigCch_UpdateFigureIntoCache (FigCch_FigureCached_t Figure, + Hie_Level_t Scope,long Cod, + unsigned Value); +bool FigCch_GetFigureFromCache (FigCch_FigureCached_t Figure, + Hie_Level_t Scope,long Cod, + unsigned *Value); + +#endif diff --git a/swad_system_config.c b/swad_system_config.c index 9d279f2e..5c9db82d 100644 --- a/swad_system_config.c +++ b/swad_system_config.c @@ -36,6 +36,7 @@ #include "swad_config.h" #include "swad_course.h" #include "swad_database.h" +#include "swad_figure_cache.h" #include "swad_form.h" #include "swad_help.h" #include "swad_hierarchy.h" @@ -130,13 +131,28 @@ static void SysCfg_Configuration (bool PrintView) /***** Shortcut to the country *****/ SysCfg_Shortcut (PrintView); - NumCtrsWithMap = Ctr_GetNumCtrsWithMapInSys (); + /***** Get number of centres with map *****/ + if (!FigCch_GetFigureFromCache (FigCch_NUM_CTRS_WITH_MAP,Hie_SYS,-1L, + &NumCtrsWithMap)) + { + // Not updated recently in cache ==> compute and update it in cache + NumCtrsWithMap = Ctr_GetNumCtrsWithMapInSys (); + FigCch_UpdateFigureIntoCache (FigCch_NUM_CTRS_WITH_MAP,Hie_SYS,-1L, + NumCtrsWithMap); + } + if (PrintView) /***** QR code with link to the country *****/ SysCfg_QR (); else { - NumCtrs = Ctr_GetNumCtrsInSys (); + /***** Get number of centres *****/ + if (!FigCch_GetFigureFromCache (FigCch_NUM_CTRS,Hie_SYS,-1L,&NumCtrs)) + { + // Not updated recently in cache ==> compute and update it in cache + NumCtrs = Ctr_GetNumCtrsInSys (); + FigCch_UpdateFigureIntoCache (FigCch_NUM_CTRS,Hie_SYS,-1L,NumCtrs); + } /***** Number of countries, number of institutions, @@ -336,6 +352,7 @@ static void SysCfg_QR (void) static void SysCfg_NumCtys (void) { extern const char *Txt_Countries; + unsigned NumCtys; /***** Number of countries ******/ HTM_TR_Begin (NULL); @@ -347,7 +364,13 @@ static void SysCfg_NumCtys (void) HTM_TD_Begin ("class=\"LB\""); Frm_StartFormGoTo (ActSeeCty); HTM_BUTTON_SUBMIT_Begin (Txt_Countries,"BT_LINK DAT",NULL); - HTM_Unsigned (Cty_GetNumCtysTotal ()); + if (!FigCch_GetFigureFromCache (FigCch_NUM_CTYS,Hie_SYS,-1L,&NumCtys)) + { + // Not updated recently in cache ==> compute and update it in cache + NumCtys = Cty_GetNumCtysTotal (); + FigCch_UpdateFigureIntoCache (FigCch_NUM_CTYS,Hie_SYS,-1L,NumCtys); + } + HTM_Unsigned (NumCtys); HTM_BUTTON_End (); Frm_EndForm (); HTM_TD_End (); @@ -362,6 +385,7 @@ static void SysCfg_NumCtys (void) static void SysCfg_NumInss (void) { extern const char *Txt_Institutions; + unsigned NumInss; /***** Number of institutions ******/ HTM_TR_Begin (NULL); @@ -371,7 +395,13 @@ static void SysCfg_NumInss (void) /* Data */ HTM_TD_Begin ("class=\"DAT LB\""); - HTM_Unsigned (Ins_GetNumInssTotal ()); + if (!FigCch_GetFigureFromCache (FigCch_NUM_INSS,Hie_SYS,-1L,&NumInss)) + { + // Not updated recently in cache ==> compute and update it in cache + NumInss = Ins_GetNumInssTotal (); + FigCch_UpdateFigureIntoCache (FigCch_NUM_INSS,Hie_SYS,-1L,NumInss); + } + HTM_Unsigned (NumInss); HTM_TD_End (); HTM_TR_End (); @@ -384,6 +414,7 @@ static void SysCfg_NumInss (void) static void SysCfg_NumDegs (void) { extern const char *Txt_Degrees; + unsigned NumDegs; /***** Number of degrees *****/ HTM_TR_Begin (NULL); @@ -393,7 +424,13 @@ static void SysCfg_NumDegs (void) /* Data */ HTM_TD_Begin ("class=\"DAT LB\""); - HTM_Unsigned (Deg_GetNumDegsTotal ()); + if (!FigCch_GetFigureFromCache (FigCch_NUM_DEGS,Hie_SYS,-1L,&NumDegs)) + { + // Not updated recently in cache ==> compute and update it in cache + NumDegs = Deg_GetNumDegsTotal (); + FigCch_UpdateFigureIntoCache (FigCch_NUM_DEGS,Hie_SYS,-1L,NumDegs); + } + HTM_Unsigned (NumDegs); HTM_TD_End (); HTM_TR_End (); @@ -406,6 +443,7 @@ static void SysCfg_NumDegs (void) static void SysCfg_NumCrss (void) { extern const char *Txt_Courses; + unsigned NumCrss; /***** Number of courses *****/ HTM_TR_Begin (NULL); @@ -415,7 +453,13 @@ static void SysCfg_NumCrss (void) /* Data */ HTM_TD_Begin ("class=\"DAT LB\""); - HTM_Unsigned (Crs_GetNumCrssTotal ()); + if (!FigCch_GetFigureFromCache (FigCch_NUM_CRSS,Hie_SYS,-1L,&NumCrss)) + { + // Not updated recently in cache ==> compute and update it in cache + NumCrss = Crs_GetNumCrssTotal (); + FigCch_UpdateFigureIntoCache (FigCch_NUM_CRSS,Hie_SYS,-1L,NumCrss); + } + HTM_Unsigned (NumCrss); HTM_TD_End (); HTM_TR_End (); @@ -429,6 +473,20 @@ static void SysCfg_NumUsrsInCrss (Rol_Role_t Role) { extern const char *Txt_Users_in_courses; extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS]; + unsigned NumUsrsInCrss; + static FigCch_FigureCached_t Figure[Rol_NUM_ROLES] = + { + [Rol_UNK ] = FigCch_NUM_USRS_IN_CRSS, // Any users in courses + [Rol_GST ] = FigCch_UNKNOWN, // Not applicable + [Rol_USR ] = FigCch_UNKNOWN, // Not applicable + [Rol_STD ] = FigCch_NUM_STDS_IN_CRSS, // Students + [Rol_NET ] = FigCch_NUM_NETS_IN_CRSS, // Non-editing teachers + [Rol_TCH ] = FigCch_NUM_TCHS_IN_CRSS, // Teachers + [Rol_DEG_ADM] = FigCch_UNKNOWN, // Not applicable + [Rol_CTR_ADM] = FigCch_UNKNOWN, // Not applicable + [Rol_INS_ADM] = FigCch_UNKNOWN, // Not applicable + [Rol_SYS_ADM] = FigCch_UNKNOWN, // Not applicable + }; /***** Number of users in courses *****/ HTM_TR_Begin (NULL); @@ -440,11 +498,19 @@ static void SysCfg_NumUsrsInCrss (Rol_Role_t Role) /* Data */ HTM_TD_Begin ("class=\"DAT LB\""); - HTM_Unsigned (Usr_GetNumUsrsInCrss (Hie_SYS,-1L, - Role == Rol_UNK ? (1 << Rol_STD) | - (1 << Rol_NET) | - (1 << Rol_TCH) : // Any user - (1 << Role))); + if (!FigCch_GetFigureFromCache (Figure[Role],Hie_SYS,-1L, + &NumUsrsInCrss)) + { + // Not updated recently in cache ==> compute and update it in cache + NumUsrsInCrss = Usr_GetNumUsrsInCrss (Hie_SYS,-1L, + Role == Rol_UNK ? (1 << Rol_STD) | + (1 << Rol_NET) | + (1 << Rol_TCH) : // Any user + (1 << Role)); + FigCch_UpdateFigureIntoCache (Figure[Role],Hie_SYS,-1L, + NumUsrsInCrss); + } + HTM_Unsigned (NumUsrsInCrss); HTM_TD_End (); HTM_TR_End ();