Idees
------

Addr
 x Use VolAddr in jobmedia

Despool attributes later
 - use spool_attribute parameter (0,1,2)
 foreach spool_file (spool_files)
   ask to director ok/discard
   despool_attr
   end_of_despool

Continious Backup Linux
 - stap 
http://www.redhat.com/magazine/011sep05/features/systemtap/
http://sourceware.org/systemtap/

Deduplication:
 proba de collision en fonction de la taille du hash
  http://en.wikipedia.org/wiki/Birthday_attack

Cryptage :
 - Pouvoir configurer les algos de cryptage
 - Pouvoir choisir de crypter dans le fileset
 - Pouvoir choisir de forcer le cryptage dans la definition
   du client.

Lister les fichiers sur le client :
 - Avoir un mode comme restore
 - Avoir une api list files client=xxx where=yyy
  Dans la filed/job.c:handle_client_request, ajouter une commande
  dans struct s_cmds cmds; et si possible utiliser le code de finlib
 - A voir, pourquoi ne pas utiliser mark/unmark comme dans une resto
   pour construire un fileset ?

Sauvegarde des postes nomades :
 - Le client doit pouvoir initier les sauvegardes
 - Au niveau firewall, il ne doit y avoir que 1 connexion (1)
		    
					      
	     Localhost 	   |   	       	      
	      	       	   |   +-------+ (4) +---------------+
	    	       	   |   |       |<----|               |
+--------+  (5)	 +-------+ |   |       |     |   DIRECTOR    |
|        |<------+       | |   |       |---->|               |
|   FD 	 |     	 | PROXY | |   | PROXY | (3) +-------+-------+
|        +------->       <-+--->       |      	     |
+--------+  (6)  +-^-----+ (2) |       |     +-------v-------+
    	          /-\ 	   |   |       | (7) |               |
    	           |   	   |   |       +----->   STORAGE     |
    	           |       |   |       |     |               |
  Initiate backup  |       |   +-------+     +---------------+
     --------------+ 	   |   		      	      
       	   (1)	        Network       		      	      
       	       	     	       		      	      
    			       		      
(1) & (2) BEGIN Backup	       
(3) Bconsole like - Run command
(4) & (5) DIR -> (PROX <-> PROX) -> FD connection (fileset, storage..)
(6) & (7) FD -> (PROX <-> PROX) -> SD

 - Utilisation d'une sorte proxy https


Bconsole :
 p Ajouter l'historique dans la bconsole
 - Ajouter une commande pour bloquer un drive
 - Ajouter de la completion automatique sur les commandes

Sauvegarde SAN :
 - Avoir un SD sur chaque FD
 - Avoir une serie de script qui :
   * bascule le lecteur en local
   * lance le SD
   * le script de mtx doit faire ses demandes au director sur
     un autochanger commun

 - Tout le monde voit le lecteur, et le client doit demander la permission
 pour despooler son bloc de XG au director.

 - On fait du round robbin avec tout le monde, et on utilise un disque 
 local pour  spooler.

 - 50 clients qui spoolent en local, c'est plus rapide que vers 1 point 
 central


Gestion des stats :
 - Ajouter la gestion des stats dans le client et le sd
   - Ajouter un M_STATS dans la gestion des messages
   - gnrer un format simple UNIXSTAMP|label|unit|value
   - possibilit d'ajouter a dans la base de donne ou dans rrd

Exchange backup:
http://www.petri.co.il/brick_level_backup_of_mailboxes_by_using_exmerge.htm

API :

 - apr (apache portable runtime) pour les exemples de chargement
   de module dynamique (win32, linux, etc...)
   http://svn.apache.org/viewvc/apr/apr/trunk/dso/

 - exemple apache
   http://modules.apache.org/doc/API.html

 - comment charger les librairies dependantes d'un hook
 ex: ACL  -> -lacl
     GZIP -> -lgz

 - nommer les hook (a la place d'une structure de pointeur)
 ex:
	"action", mod_action_handler

 - interface
   - opendir
   - readdir
   - closedir
   - mkdir
   - stat
   - open
   - close
   - read
   - write
   - seek
   - get_perm
   - set_perm
   - configuration... (ajout automatique avant de charger le fichier de conf)
   - init
   - destroy

   - version
   - name

 - exemple de hook/module
   - cryptage ?
   - checksum (MD5/SHA1)
   - ACL/droits
   - compression (LZO, GZIP, BZIP)

 - initialiser le jcr avec seulement les hooks utiles

 - configuration 
   - declarer les modules utiles
   - les options doivent utiliser le nom du module
 ex:
      GZIP level = 2
      ACL use uid = yes
      etc...

TODO
----

bweb :
  - Support sqlite
    SELECT strftime('%Y-%m-%d', Job.StartTime) FROM Job LIMIT 1;
  x Voir les groupes d'un client
  - Overview, pouvoir choisir entre la job_old et l'autre
  - utiliser des noms de table plus proche (brestore -> bweb ?)
  x Balloon
Btw., the vertical axis was the number of files 
while the size of the ballon is the volume (in MB 
or GB).  Those could be switched, though, depending on what looks better.

What are you using for color-coding the ballons? 
That could be a variety of different things like 
client, client group, backup level (full, 
incremental, etc.,) that adds context to the size 
and position that is already present in the chart.

 x Ajouter mount,umount,release,status pour chaque device
 - Ajouter le viewfileset dans l'interface de resto
 x Ajouter la labelisation de bande et l'ajout de media (add et label)
 - Ajouter la possibilit de lancer des migrations et des
 verification. 
 - Quand on deplace un media, il faut prendre le enabled depuis
   la nouvelle localisation (en javascript)
  o On ajoute une combo (Backup/Migration/Verify)
  o On peut regarder dans l'historique des job quel est le bon type
  o Quand on relance, on spcifie le type directement
  o Il faut adapter le status client pour traiter les autres type
 de job (par exemple, si c'est pas un backup/restore, pas de status dir)


 x Ajouter une vue par groupe et par date (sur 7, 15 ou 30 jours)

              lu ma me je ve sa di
  groupe1     v  v  x  w  v  v  v             q1
   |-- s1     v  v  v  v  v  v  v             q2
   |-- s2     v  v  x  v  v  v  v
   `-- s3     v  v  v  w  v  v  v

---8<-------8<--------8<--------8<----------8<------------------

ALTER TABLE Status ADD COLUMN severity int;
UPDATE status SET severity = 15;
UPDATE status SET severity = 100 where jobstatus = 'f';
UPDATE status SET severity = 90 where jobstatus = 'A';
UPDATE status SET severity = 10 where jobstatus = 'T';

-- Affiche par groupe et date le statut des jobs (q1)
SELECT date_part('day', date) AS day, date, client_group_name, JobStatusLong, 
       JobStatus, nb_job, joberrors
FROM (
  SELECT date_trunc('day', job_old.StartTime) AS date, 
         MAX(severity)  AS severity,
         COUNT(1)       AS nb_job,
	 SUM(JobErrors) AS joberrors,
         client_group_name
    FROM job_old
    JOIN client_group_member USING (ClientId)
    JOIN client_group        USING (client_group_id)
    JOIN Status              USING (JobStatus)
   WHERE StartTime > '2007-10-01' AND StartTime < '2007-11-19'
  
   GROUP BY client_group_name, date
) AS sub JOIN Status USING (severity)
 ORDER BY client_group_name, date

-- Affiche un client_group en detail (q2)
SELECT date, client, JobStatusLong, JobStatus, nb_job, joberrors
FROM (
  SELECT date_trunc('day', job_old.StartTime) AS date,
	 Client.Name    AS client,
         MAX(severity)  AS severity,
         COUNT(1)       AS nb_job,
         SUM(JobErrors) AS joberrors
    FROM job_old
    JOIN client_group_member USING (ClientId)
    JOIN client_group        USING (client_group_id)
    JOIN Client              USING (ClientId)
    JOIN Status              USING (JobStatus)
   WHERE StartTime > '2007-10-01'
     AND client_group_name = '0-SAVES_SIGMA1'

   GROUP BY client, date
) AS sub JOIN Status USING (severity)
 ORDER BY client, date

---8<-------8<--------8<--------8<----------8<------------------

 - Quand on clique dessus on arrive sur la liste des jobs en question
   Groupe -> Jobs
   Job    -> Log

 x Ajouter une variable pour remplacer NOW() dans les queries
   origin = arg->{origin} || NOW();
 - Ajouter des stats en %

---8<-------8<--------8<--------8<----------8<------------------

SELECT  client_group_name, (nb_ok::float/(nb_ok+nb_other)*100)::numeric(6,3) AS percent_ok
FROM (

     SELECT 
       SUM(CASE WHEN JobStatus='T' THEN 1 
                ELSE 0 END) AS nb_ok,
       SUM(CASE WHEN JobStatus='A' THEN 1 
		WHEN JobStatus='f' THEN 1
		WHEN JobStatus='E' THEN 1 
		WHEN JobStatus='e' THEN 1 
                ELSE 0 END) AS nb_other,
       client_group_name
      FROM job_old 
      JOIN client_group_member USING (ClientId)
      JOIN client_group        USING (client_group_id)

     WHERE StartTime > '2007-10-01'
     GROUP BY client_group_name
) AS subq

SELECT  Name, (nb_ok::float/(nb_ok+nb_other)*100)::numeric(6,3) AS percent_ok
FROM (

     SELECT 
       SUM(CASE WHEN JobStatus='T' THEN 1 
                ELSE 0 END) AS nb_ok,
       SUM(CASE WHEN JobStatus='A' THEN 1 
		WHEN JobStatus='f' THEN 1
		WHEN JobStatus='E' THEN 1 
		WHEN JobStatus='e' THEN 1 
                ELSE 0 END) AS nb_other,
       Client.Name AS name
      FROM job_old 
      JOIN Client       USING (ClientId)

     WHERE StartTime > '2007-10-01'
       AND JobStatus IN ('T', 'A', 'f', 'E', 'e')
     GROUP BY Client.Name
) AS subq



---8<-------8<--------8<--------8<----------8<------------------

   Nb backup OK
  -------------  x 100 => par groupe de client
   Nb backup

 - Il faut ajouter une estimation des jobs qui auraient
   du se lancer (a voir avec les schedules)

 - Affichage en html/csv pour des stats 
  grp, nb client, nb backup, nb ok, nb err, nb cancel, 
  %ok, nb files, nb gig, time

 - Ajouter la liste des fichiers (quand il n'y en a pas trop)
 - Ajouter un mode qui compte le nombre de fichier sous bfileview
 x Ajouter une estimation de progression du backup bas sur le nombre
   de fichier et le nombre de Mo
 x Ajouter un bouton suivant/precedant dans la vue des logs
 x Ajouter la liste des medias qui vont/ont expirer et les pruner
 x Fixer les purge/prune de multiple volumes
 x Ajouter une gestion des utilisateurs avec des roles
   o Liste des roles possibles
     * view_stats
     * configure
     * run_job
     * run_restore
     * view_history
     * view_log
     * view_media
     * view_pool
     * update_media
     * view_autochanger
     * update_autochanger
     * cancel_job

   o Avoir des profiles ayant certains roles
     * admin (all)
     * customer (view_stats, view_history, view_log)
     * production (all - configure)
     ...

   o Pour faire la difference entre les groupes de la vue et
     les groupes d'acl, il faut ajouter un champs dans la table
     client_group (visible bool).

   o Ajout de 4 tables dans le catalogue
       - bweb_user (userid, username, passwd, comment) passwd with apache ?
       - bweb_role (roleid, rolename)
       - bweb_role_member (roleid, userid)

       - bweb_client_group_acl (client_group_id, userid)
       - bweb_pool_acl (poolid, userid)

 o Il faudrait aussi pouvoir choisir le login admin...

 x On specifie par user si on veut filter par les groupes (gestion un peu
   chiante, il faut ajouter les hosts dans les groupes, sinon, ils sont
   invisibles)

 x On recupere ce champs quand on check les can_do(); et apres, on le regarde
   avant d'envoyer le JOIN de filtre. (Attention, admin n'est pas soumis a ca)
   
 x On peut ajouter une option dans la Config pour activer ce mode ou pas. 

 x Regarder la possibilite de recuperer toutes les roles au debut pour
   adapter les pages web... Il n'y a que les menus/actions autorises qui
   seraient affiches. (bp cancel => role cancel_job, configuration => role configure)

 * on utilise le commentaire depuis une page web, comme ca
   on gere la traduction sans toucher a la base

CREATE TABLE bweb_user
(
	userid       serial not null,
	username     text not null,
	use_acl      boolean default false,
        comment      text default '',
	passwd       text default '',
	primary key (userid)
);
CREATE UNIQUE INDEX bweb_user_idx on bweb_user (username);

CREATE TABLE bweb_role
(
	roleid       serial not null,
	rolename     text not null,
--	comment      text default '',
	primary key (roleid)
);
CREATE UNIQUE INDEX bweb_role_idx on bweb_role (rolename);

INSERT INTO bweb_role (rolename) VALUES ('r_user_mgnt');
INSERT INTO bweb_role (rolename) VALUES ('r_delete_job');
INSERT INTO bweb_role (rolename) VALUES ('r_prune');
INSERT INTO bweb_role (rolename) VALUES ('r_purge');
INSERT INTO bweb_role (rolename) VALUES ('r_group_mgnt');
INSERT INTO bweb_role (rolename) VALUES ('r_location_mgnt');
INSERT INTO bweb_role (rolename) VALUES ('r_cancel_job');
INSERT INTO bweb_role (rolename) VALUES ('r_run_job');
INSERT INTO bweb_role (rolename) VALUES ('r_configure');
INSERT INTO bweb_role (rolename) VALUES ('r_client_status');
INSERT INTO bweb_role (rolename) VALUES ('r_view_job');

CREATE TABLE  bweb_role_member
(
	roleid       integer not null,
	userid       integer not null,
	primary key (roleid, userid)
);

CREATE TABLE  bweb_client_group_acl
(
	client_group_id       integer not null,
	userid                integer not null,
	primary key (client_group_id, userid)
);

 - Integrer brestore en mode javascript
   o ajouter une api 
       .ls_dir(jobid,pathid)
       .ls_file(jobid,pathid)
       .get_pathid(jobid,"/")
       .genbsr (fileid, fileid, fileid, fileid, fileid...)
           -> on peut utiliser une table dans la base pour faire ca
              cf bat

> 1. Unloading tapes assistent.
>
> I'm using a script which selects tapes to unload. The idea is to
> remove all volumes from the library that contain a current set of
> backups. Basically, find the volumes from the most recent full backups
> and all volumes that depend on these. Ignore older fulls and their
> differentials and incrementals.
>
> This is to ensure that, at the time volumes are unloaded, a complete
> set of backups can be stored safely.

Already ok
 Jobs -> Job Zoom -> View Media -> Select them -> Eject

Yes, it's a very good idea, i see no difficulty to implement this kind of
tool.

Users go to 
  Media -> Made a Safe backup set 
        -> Select Client(s) -> Select Job(s) -> Backup set

I think that i can do some sort of assistant to that.
(with next, next next)


> While volumes are prepared for unloading, I disable them, so Bacula
> will not try to use them. Later, they are automatically re-enabled.

x Do you use the Enabled flag for that ? It's a good idea.

> Move these volumes (if possible) to the export slots.

I have already some code for that, but at this time it doesn't use
the mtx-script from bacula. (or bacula-sd commands)

I have to change this, so user have a working mtx-scripts, and we use
it everywhere. (The best solution is to send command to bacula-dir)

> Later, request volumes to fill up the pools so there are usable
> volumes for later backups around. Load these volumes from the import
> slots to the regular working slots, and do an 'update slots'.

I use the Scratch pool for this sort of things, but we could use an other 
assistant for that.

Media -> I/O -> Fill pools -> Select pool(s) -> import selections

bschedule:
 x Bug dans la determination des jours de la semaine (exemple de la full
  le premier dimanche du mois)

manuel :
 - Avoir la version 2.0 et la version 2.2 en ligne (pour que les utilisateurs
   ne se trompent pas dans les versions)
 - Supprimer les (need bacula >= 1.xx) (dans la derniere version)

bacula :
 - Faire un test de non regression avec pleins d'erreur
   o pb inclusion (distante, locale)
   o pb exclusion (distante, locale)
   o pb execution de commande
   o pb de config avec test du -t des differents daemon
 x Utiliser PQescapeStringConn a la place de PQescapeString
 - Utiliser la lib pcre
 - Rendre les scripts bacula-ctl-xxx LSB
 x Pouvoir utiliser les uid numeriques dans le backup des acl
 - Avoir un script qui dump la configuration pour faire
   des bug reports
 p modifier l'organisation de la table version (pour pouvoir ajouter
   les versions de bweb par exemple)
 - utiliser la meme fonction pour read_close_session et append_close_session
 x pb dans le message de chargement d'une bande pendant une resto

	Please mount Volume "R40175" or label a new one for
	Pas le bon message pour une resto (label a new one)
 - Impossible de lancer une restauration en meme temps qu'un backup sur
   un autochanger. Le code dans jobq.c qui controle les MaxConcurrentJobs
   ne prend pas en compte les autochanger avec plusieurs drives. Ce code
   fait surement doublon avec le nouveau code de reservation.
   Il faudrait le simplifier, et compter les jobs de restauration comme les
   jobs normaux. Le patch prcdent ne changeait pas le MaxConcurrentJobs
   comme il faut  la fin du backup.

 x Accurate backup
   o Envoyer la liste de tous les fichiers au client dans un format simple
    /path/	LSTAT			# un / a la fin pour un repertoire
    /path/file	LSTAT

   o Le client construit un hash disque (ou en memoire ou les deux)
   o A chaque repertoire/fichier on verifie la presence du fichier dans le hash
     et on peut aussi comparer date/taille/bloc
      - Si le fichier n'est pas dedans, on le backup
      - Si le fichier est present on verifie les attributs et on mark le fichier comme vu
   o A la fin, on parcours tous le hash pour trouver les fichiers qui ne sont pas vu et 
     on envoie la liste des fichiers supprimes avec le fileindex=0 et pourquoi pas la date
     du jour dans le champ mtime
   o Utiliser systematiquement l'option ignorecase sous windows
   p Ajouter une option pour avoir la table de stat
      Enable Statistic = yes/no
      Statistic retention = 4 years
   o use mmap to map hash ? (on 32b, we are limited to 1 or 2GB)

#ifndef _WIN32
       ef->data = mmap(NULL, ef->data_size, PROT_READ,
                       MAP_SHARED, fileno(ef->fp), 0);
#else
       fm = CreateFileMapping((HANDLE) _get_osfhandle (fileno(ef->fp)),
                              NULL,
                              PAGE_READONLY,
                              0,
                              0,
                              NULL);
       ef->data = MapViewOfFile(fm,
                                FILE_MAP_READ,
                                0,
                                0,
                                ef->data_size);
       CloseHandle(fm);
#endif
 
        ef = eet_internal_read(ef);
        if (!ef)
@@ -892,11 +862,7 @@
        free(ef->header);
      }
 
#ifndef _WIN32
   if (ef->data) munmap((void*)ef->data, ef->data_size);
#else
   if (ef->data) UnmapViewOfFile (ef->data);
#endif

if (ef->fp) fclose(ef->fp);

  - Accurate backup (kern)
1. Run bconsole
2. Dir -> FD run job
*3. FD does a normal backup and at the same time makes a list of all files on 
the system (in the FileSet), marking which ones were just now backed up.
4. For each file backed up send attributes/data to SD.  Note, this is done 
during step 3 above. Minor difference, the connection with the SD is not 
dropped at the end of the backup -- see later.
*5. Send the list of all files including those backed up to the Dir
  --> Send to SD and DIR at the same time ? 
        filed/backup.c/encode_and_send_attributes

6. Dir computes files and deleted files.
7. Dir sends list of additional files (new files) to backup, and list of files
deleted.
8. FD does backup of files Dir says to save.
9. FD sends SD attrs of backed up files
10. FD sends SD delete records for files Dir wants deleted.
*11. FD connection to SD can be closed, this part of the backup is done.
*12. FD sends new list of files just backed up to Dir
*13. Dir adds newly backed up files to previous list sent by FD
*14. Dir "batch" inserts complete new list in the catalog (I forgot the name 
of the new table). Note this table has nothing to do with the File table.
*15. Dir deletes previous list in catalog.
*16. Dir does normal batch insert of attributes from SD, but must handle 
deleted records. Note, this will probably happen at the same time as the 
items 13-15.



  - TODO:
  0001088: volume FirstWritten attribute is set to time of mount request, not time of first write
  Description 	When a Bacula job requests mounting a tape volume that is not present in the drive,
  once the tape is mounted, its FirstWritten attribute is set to the time when the volume was requested.
  Consequently, if the job has been waiting longer than the maximum use duration of the volume,
  the volume is promoted to Used immediately because the maximum use duration has apparently expired before
  the use has even started.

To avoid that, the FirstWritten attribute should be set to the time the volume was mounted (= the current time when the setting takes place).

 x Backup a file that is not in accurate list (change NOCHG to LINK, FILE, etc..)
 * Manage JobFiles (Deleted compte pour 1 ?)

 x Utiliser le check_accurate dans find_one et declencher le save_file
 si besoin en desactivant le incremental.
 x ne va pas marcher avec le strip path (la recherche est faite avant le strip path)
 * on peut utiliser le champs LStat de la base pour noter que le fichier est supprim...
  
 CREATE TEMPORARY TABLE btemp2 AS (
  SELECT max(FileId) as FileId, PathId, FilenameId 
    FROM (SELECT FileId, PathId, FilenameId FROM File WHERE JobId IN (39867,40341)) AS F
   GROUP BY PathId, FilenameId )

 SELECT Path.Path, Filename.Name, File.FileIndex, File.JobId, File.LStat 
 FROM (
  SELECT max(FileId) as FileId, PathId, FilenameId 
    FROM (SELECT FileId, PathId, FilenameId FROM File WHERE JobId IN (11,13)) AS F
   GROUP BY PathId, FilenameId
  ) AS Temp 
 JOIN Filename ON (Filename.FilenameId = Temp.FilenameId) 
 JOIN Path ON (Path.PathId = Temp.PathId) 
 JOIN File ON (File.FileId = Temp.FileId)
 WHERE FileIndex > 0


  SELECT File.FileIndex, Path.Path, Filename.Name, File.LStat
    FROM btemp2 JOIN Path USING (PathId) JOIN Filename USING (FilenameId)
                JOIN File USING (FileId)
   WHERE File.FileIndex > 0

 DROP TABLE btemp2
*/
/*
SELECT DISTINCT ON (PathId, FilenameId) FileIndex, Path, Name, LStat
  FROM File JOIN Filename USING (FilenameId) JOIN Path USING (PathId) WHERE JobId IN (40341)
 ORDER BY PathId, FilenameId, JobId DESC
*/

 - .api mode:
Some ideas :
- Every dates have to be in ISO format
YYYY-MM-DD HH:MM:SS
- JobLevel, JobStatus, etc.. have to use C constant T,R,a,A,f...
- Sizes are always in bytes (no suffix)
- Numbers have to be used without commas
- If we change (add) something,  we must always add new elements
at the end.

For director status on running jobs, it will be great to display :
JobId, Client name, Job Name, Level, Start Time and Status


 x Utiliser une alist dans les runscripts

RunScript {
   console = "xxxx"
   console = "yyy"
   console = "zzzz"
}

or possibly

RunScript {
   console = "xxxx", "yyyy", "zzzz" 
   console = "aaaa"
}

 o cleanup bextract to use filed code

