Kern's ToDo List
- 07 Septermber 2004
+ 08 Septermber 2004
Major development:
Project Developer
you lost/broke the Catalog -- do the same for "I know my
file is there how do I get it back?".
+- Add "Multiple connections = yes/no" to catalog resource.
+- Add "Rerun failed levels = yes/no" to Job resource.
+
Maybe for 1.35:
- Look at patches/bacula_db.b2z postgresql that loops during restore.
- Minimal autochanger handling in Bacula and in btape.
- Look into how tar does not save sockets and the possiblity of
not saving them in Bacula (Martin Simmons reported this).
- The next two lines will show them.
- localmounts=`awk '/ext/ { print $2 }' /proc/mounts` # or whatever
+- Add All Local Partitions = yes to new style saves.
+- localmounts=`awk '/ext/ { print $2 }' /proc/mounts` # or whatever
find $localmounts -xdev -type s -ls
- Fix restore jobs so that multiple jobs can run if they
are not using the same tape(s).
- look at mxt-changer.html
- Make ? do a help command (no return needed).
- Implement restore directory.
-- Add All Local Partitions = yes to new style saves.
- Document streams and how to implement them.
- Possibly implement "Ensure Full Backup = yes" looks for a failed full backup
and upgrades the current backup if one exists.
- Check that barcode reading and update slots scan works.
- Try not to re-backup a file if a new hard link is added.
- Add feature to backup hard links only, but not the data.
-- Add "All Local = yes" option to save to include all local partitions.
- Fix stream handling to be simpler.
- Add Priority and Bootstrap to Run a Job.
- Eliminate Restore "Run Restore Job" prompt by allowing new "run command
- Add display of total selected files to Restore window.
- Add tree pane to left of window.
- Add progress meter.
-- Polling does not work for restore. It tries a number of times,
- gives up, and crashes the SD.
-- Lock jcr_chain when doing attach/detach in acquire.c
-- Add assert in free_jcr if attach/detach chain active.
- Max wait time or max run time causes seg fault -- see runtime-bug.txt
- Document writing to a CD/DVD with Bacula.
-- Add check for tape alerts.
- Add a "base" package to the window installer for pthreadsVCE.dll
which is needed by all packages.
- Add message to user to check for fixed block size when the forward
- Possibly implement: Action = Unmount Device="TapeDrive1" in Admin jobs.
- Setup lrrd graphs: (http://www.linpro.no/projects/lrrd/) Mike Acar.
- Revisit the question of multiple Volumes (disk) on a single device.
-- Finish SIGHUP work.
-- Check that all change in wait status in the SD are
- signaled to the Director.
- Add a block copy option to bcopy.
- Investigate adding Mac Resource Forks.
- Finish work on Gnome restore GUI.
- Fix "llist jobid=xx" where no fileset or client exists.
-- Check pruning of restore jobs.
- From Chris Hull:
it seems to be complaining about 12:00pm which should be a valid 12
hour time. I changed the time to 11:59am and everything works fine.
then list last 20 backups.
- Add all pools in Dir conf to DB also update them to catch changed
LabelFormats and such.
-- Update volumes FromPool=xxx does all volumes.
- Pass Director resource name as an option to the Console.
- Add a "batch" mode to the Console (no unsolicited queries, ...).
-- Add code to check for tape alerts -- tapeinfo.
-- Make sure list of Volumes needed is in correct order for restore.
- See havana.
-- Remove paths (and files that reference them) that have no trailing slash
- in dbcheck -- or add a trailing slash.
-- Remove Filenames (and files that reference them) that have a trailing
- slash in dbcheck -- or remove the trailing slash.
-- Remove orphaned paths/filenames by copying them to a new table with a
- reference count, then mark all referenced files/paths and remove unreferenced
- ones.
- Add a .list all files in the restore tree (probably also a list all files)
Do both a long and short form.
- Allow browsing the catalog to see all versions of a file (with
stat data on each file).
- Restore attributes of directory if replace=never set but directory
did not exist.
-- Allow "delete job jobid=xxx,yyy,aaa-bbb" i.e. list + ranges.
- Use SHA1 on authentication if possible.
- See comtest-xxx.zip for Windows code to talk to USB.
- Make btape accept Device Names in addition to Archive names.
- Add disk seeking on restore. - Allow
for optional cancelling of SD and FD in case DIR
gets a fatal error. Requested by Jesse Guardiani <jesse@wingnet.net>
-- Bizarre message: Error: Could not open WriteBootstrap file:
-- Build console in client only build.
- Add "limit=n" for "list jobs"
- Check new HAVE_WIN32 open bits.
- Check if the tape has moved before writing.
- Handling removable disks -- see below:
-- Multiple drive autochanger support -- see below.
- Keep track of tape use time, and report when cleaning is necessary.
-- Fix FreeBSD mt_count problem.
- Add FromClient and ToClient keywords on restore command (or
BackupClient RestoreClient).
-- Automatic "update slots" on user configuration directive when a
- slot error occurs.
- Implement a JobSet, which groups any number of jobs. If the
JobSet is started, all the jobs are started together.
Allow Pool, Level, and Schedule overrides.
- Enhance cancel to timeout BSOCK packets after a specific delay.
-- When I restore to Windows the Created, Accessed and Modifiedtimes are
- those of the time of the restore, not those of the originalfile.
- The dates you will find in your restore log seem to be the original
- creation dates
-- Volume "add"ed to Pool gets recycled in first use. VolBytes=0
-- If a tape is recycled while it is mounted, Stanislav Tvrudy must do an
- additional mount to deblock the job.
-- From Johan Decock:
- bscan: sql_update.c:65 UPDATE File SET MD5='Ij+5kwN6TFIxK+8l8+/I+A' WHERE FileId=0
- bscan: bscan.c:1074 Could not add MD5/SHA1 to File record. ERR=sql_update.c:65 Update problem: affected_rows=0
- Do scheduling by UTC using gmtime_r() in run_conf, scheduler, and
ua_status.!!! Thanks to Alan Brown for this tip.
- Look at updating Volume Jobs so that Max Volume Jobs = 1 will work
correctly for multiple simultaneous jobs.
- Correct code so that FileSet MD5 is calculated for < and | filename
generation.
-- Mark Volume in error on error from WEOF.
- Implement the Media record flag that indicates that the Volume does disk
addressing.
- Implement VolAddr, which is used when Volume is addressed like a disk,
- Fix fast block rejection (stored/read_record.c:118). It passes a null
pointer (rec) to try_repositioning().
- Look at extracting Win data from BackupRead.
-- Having dashes in filenames apparently creates problems for restore
- by filename??? hard to believe.
- Implement RestoreJobRetention? Maybe better "JobRetention" in a Job,
which would take precidence over the Catalog "JobRetention".
- Implement Label Format in Add and Label console commands.
resources, like Level? If so, I think I'd make it an optional directive
in Job, Client, and Pool, with precedence such that Job overrides Client
which in turn overrides Pool.
-- Print a message when a job starts if the conf file is not current.
- Spooling ideas taken from Volker Sauer's and other's emails:
> IMHO job spooling should be turned on
even more important, it's not flaky
it has an open access catalog, opening many possibilities
it's pushing toward heterogeneous systems capability
- simple things:
- I don't remember an include file directive for config files
- (not filesets, actual config directives)
- can you check the configs without starting the daemon?
- some warnings about possible common mistakes
big things:
- doing the testing and blessing of concurrent backup writes
- this is absolutely necessary in the enterprise
- easy user recovery GUI with full access checking
Macintosh file client
macs are an interesting niche, but I fear a server is a rathole
working bare iron recovery for windows
- much better handling on running config changes
- thinking through the logic of what happens to jobs in progress
the option for inc/diff backups not reset on fileset revision
a) use both change and inode update time against base time
b) do the full catalog check (expensive but accurate)
to the user, who would then use "mount" as described above
once he had actually inserted the disk.
- Implement dump/print label to UA
-- Implement disk spooling. Two parts: 1. Spool to disk then
- immediately to tape to speed up tape operations. 2. Spool to
- disk only when the tape is full, then when a tape is hung move
+- Spool to disk only when the tape is full, then when a tape is hung move
it to tape.
- Scratch Pool where the volumes can be re-assigned to any Pool.
- bextract is sending everything to the log file ****FIXME****
if full status requested or if some level of debug on.
- Make database type selectable by .conf files i.e. at runtime
- Set flag for uname -a. Add to Volume label.
-- Implement throttled work queue.
- Restore files modified after date
- SET LD_RUN_PATH=$HOME/mysql/lib/mysql
-- Implement Restore FileSet=
-- Create a protocol.h and protocol.c where all protocol messages
- are concentrated.
- Remove duplicate fields from jcr (e.g. jcr.level and jcr.jr.Level, ...).
- Timout a job or terminate if link goes down, or reopen link and query.
- Concept of precious tapes (cannot be reused).
*/
+/*
+ * UTF-8
+ * If the top bit of a UTF-8 string is 0 (8 bits), then it
+ * is a normal ASCII character.
+ * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then
+ * it is the start of a series of chars (up to 5)
+ * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80)
+ */
+
#ifdef TEST_PROGRAM
#include <stdio.h>
/* Function Prototypes */
-static int input_char(void);
-static int t_gnc(void);
+static unsigned int input_char(void);
+static unsigned int t_gnc(void);
static void insert_space(char *curline, int line_len);
-static void forward(int i, char *str, int str_len);
-static void backup(int i);
+static void insert_hole(char *curline, int line_len);
+static void forward(char *str, int str_len);
+static void backup(char *curline);
static void delchr(int cnt, char *curline, int line_len);
static int iswordc(char c);
static int next_word(char *ldb_buf);
static void t_insert_line(void);
static void t_delete_line(void);
static void t_clrline(int pos, int width);
-void t_sendl(char *msg, int len);
+void t_sendl(const char *msg, int len);
void t_send(char *msg);
void t_char(char c);
static void asclrs();
static void rawmode(FILE *input);
static void normode(void);
-static int t_getch();
+static unsigned t_getch();
static void asclrl(int pos, int width);
static void asinsl();
static void asdell();
/*
* New style string mapping to function code
*/
-static int do_smap(int c)
+static unsigned do_smap(unsigned c)
{
char str[MAX_STAB];
int len = 0;
stab_t *tstab;
int i, found;
+ unsigned cm;
len = 1;
str[0] = c;
str[1] = 0;
- if (c != 27) {
- c = char_map[c];
- }
- if (c <= 0) {
+ cm = char_map[c];
+ if (cm == 0) {
return c;
+ } else {
+ c = cm;
}
for ( ;; ) {
found = 0;
/* Get the next character from the terminal - performs table lookup on
the character to do the desired translation */
-static int
+static unsigned int
input_char()
{
- int c;
+ unsigned c;
if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */
c = do_smap(c);
{
char curline[2000]; /* edit buffer */
int noline;
- int c;
+ unsigned c;
+ int more;
+ int i;
if (first) {
poolinit(); /* build line pool */
clrbrk();
break;
}
- switch (c=(int)input_char()) {
+ switch (c=input_char()) {
case F_RETURN: /* CR */
t_sendl("\r\n", 2); /* yes, print it and */
goto done; /* get out */
delchr(1, curline, sizeof(curline)); /* delete one character */
break;
case F_CSRLFT: /* Backspace */
- backup(1);
+ backup(curline);
break;
case F_CSRRGT:
- forward(1,curline, sizeof(curline));
+ forward(curline, sizeof(curline));
break;
case F_ERSCHR: /* Rubout */
- backup(1);
+ backup(curline);
delchr(1, curline, sizeof(curline));
break;
case F_DELEOL:
cl = cp;
break;
case F_NXTWRD:
- forward(next_word(curline),curline, sizeof(curline));
+ i = next_word(curline);
+ while (i--) {
+ forward(curline, sizeof(curline));
+ }
break;
case F_PRVWRD:
- backup(prev_word(curline));
+ i = prev_word(curline);
+ while (i--) {
+ backup(curline);
+ }
break;
case F_DELWRD:
delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
/* Note fall through */
case F_DELLIN:
case F_ERSLIN:
- backup(cp); /* backup to beginning of line */
+ while (cp > 0) {
+ backup(curline); /* backup to beginning of line */
+ }
t_clrline(0,t_width); /* erase line */
cp = 0;
cl = 0; /* reset cursor counter */
break;
case F_SOL:
- backup(cp);
+ while (cp > 0) {
+ backup(curline);
+ }
break;
case F_EOL:
while (cp < cl) {
- forward(1,curline, sizeof(curline));
+ forward(curline, sizeof(curline));
}
while (cp > cl) {
- backup(1);
+ backup(curline);
}
break;
case F_TINS: /* toggle insert mode */
}
t_honk_horn(); /* complain */
} else {
+ if ((c & 0xC0) == 0xC0) {
+ if ((c & 0xFC) == 0xFC) {
+ more = 5;
+ } else if ((c & 0xF8) == 0xF8) {
+ more = 4;
+ } else if ((c & 0xF0) == 0xF0) {
+ more = 3;
+ } else if ((c & 0xE0) == 0xE0) {
+ more = 2;
+ } else {
+ more = 1;
+ }
+ } else {
+ more = 0;
+ }
if (mode_insert) {
insert_space(curline, sizeof(curline));
}
curline[cp++] = c; /* store character in line being built */
- t_char((char)c); /* echo character to terminal */
+ t_char(c); /* echo character to terminal */
+ while (more--) {
+ c= input_char();
+ insert_hole(curline, sizeof(curline));
+ curline[cp++] = c; /* store character in line being built */
+ t_char(c); /* echo character to terminal */
+ }
if (cp > cl) {
cl = cp; /* keep current length */
+ curline[cp] = 0;
}
}
break;
{
int i;
- if (cp > cl || cl+1 > curline_len) return;
+ if (cp > cl || cl+1 > curline_len) {
+ return;
+ }
/* Note! source and destination overlap */
memmove(&curline[cp+1],&curline[cp],i=cl-cp);
cl++;
- i++;
curline[cp] = ' ';
- forward(i,curline, curline_len);
- backup(i);
+ i = 0;
+ while (cl > cp) {
+ forward(curline, curline_len);
+ i++;
+ }
+ while (i--) {
+ backup(curline);
+ }
+}
+
+
+static void
+insert_hole(char *curline, int curline_len)
+{
+ int i;
+
+ if (cp > cl || cl+1 > curline_len) {
+ return;
+ }
+ /* Note! source and destination overlap */
+ memmove(&curline[cp+1], &curline[cp], i=cl-cp);
+ cl++;
+ curline[cl] = 0;
}
/* Move cursor forward keeping characters under it */
static void
-forward(int i, char *str, int str_len)
+forward(char *str, int str_len)
{
- while (i--) {
- if (cp > str_len) {
- return;
- }
- if (cp>=cl) {
- t_char(' ');
- str[cp+1] = ' ';
- } else {
- t_char(str[cp]);
+ if (cp > str_len) {
+ return;
+ }
+ if (cp >= cl) {
+ t_char(' ');
+ str[cp+1] = ' ';
+ str[cp+2] = 0;
+ } else {
+ t_char(str[cp]);
+ if ((str[cp] & 0xC0) == 0xC0) {
+ cp++;
+ while ((str[cp] & 0xC0) == 0x80) {
+ t_char(str[cp]);
+ cp++;
+ }
+ cp--;
+ }
+ }
+ cp++;
+}
+
+/* How many characters under the cursor */
+static int
+char_count(int cptr, char *str)
+{
+ int cnt = 1;
+ if (cptr > cl) {
+ return 0;
+ }
+ if ((str[cptr] & 0xC0) == 0xC0) {
+ cptr++;
+ while ((str[cptr] & 0xC0) == 0x80) {
+ cnt++;
+ cptr++;
}
- cp++;
}
+ return cnt;
}
/* Backup cursor keeping characters under it */
static void
-backup(int i)
+backup(char *str)
{
- for ( ; i && cp; i--,cp--) {
- t_char('\010');
+ if (cp == 0) {
+ return;
+ }
+ while ((str[cp] & 0xC0) == 0x80) {
+ cp--;
}
+ t_char('\010');
+ cp--;
}
/* Delete the character under the cursor */
static void
-delchr(int cnt, char *curline, int line_len)
+delchr(int del, char *curline, int line_len)
{
- register int i;
+ int i, cnt;
- if (cp > cl)
+ if (cp > cl || del == 0) {
return;
- if ((i=cl-cp-cnt+1) > 0) {
- memcpy(&curline[cp], &curline[cp+cnt],i);
}
- curline[cl -= cnt] = EOS;
- t_clrline(0,t_width);
- if (cl > cp) {
- forward(i=cl-cp,curline, line_len);
- backup(i);
+ while (del-- && cp > 0) {
+ cnt = char_count(cp, curline);
+ if ((i=cl-cp-cnt) > 0) {
+ memcpy(&curline[cp], &curline[cp+cnt], i);
+ }
+ cl -= cnt;
+ curline[cl] = EOS;
+ t_clrline(0, t_width);
+ i = 0;
+ while (cl > cp) {
+ forward(curline, line_len);
+ i++;
+ }
+ while (i--) {
+ backup(curline);
+ }
}
}
if (mode_wspace)
return !isspace(c);
if (c >= '0' && c <= '9')
- return TRUE;
+ return true;
if (c == '$' || c == '%')
- return TRUE;
+ return true;
return isalpha(c);
}
static void
prtcur(char *str)
{
- backup(cp);
+ while (cp > 0) {
+ backup(str);
+ }
t_clrline(0,t_width);
cp = cl = strlen(str);
- t_sendl(str,cl);
+ t_sendl(str, cl);
}
}
/* Get next character from terminal/script file/unget buffer */
-static int
+static unsigned
t_gnc()
{
return t_getch();
/* Get next character from OS */
-static int t_getch(void)
+static unsigned t_getch(void)
{
- char c;
+ unsigned char c;
if (read(0, &c, 1) != 1) {
c = 0;
}
- return (int)c;
+ return (unsigned)c;
}
/* Send message to terminal - primitive routine */
void
-t_sendl(char *msg, int len)
+t_sendl(const char *msg, int len)
{
write(1, msg, len);
}