]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/read.c
baf57f549d1cc124c09ac5e27cabc53f46bc0c1c
[bacula/bacula] / bacula / src / stored / read.c
1 /*
2  * Read code for Storage daemon
3  *
4  *     Kern Sibbald, November MM
5  *
6  *   Version $Id$
7  */
8 /*
9    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2 of
14    the License, or (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public
22    License along with this program; if not, write to the Free
23    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24    MA 02111-1307, USA.
25
26  */
27
28 #include "bacula.h"
29 #include "stored.h"
30
31 /* Forward referenced subroutines */
32
33 /* Variables used by Child process */
34 /* Global statistics */
35 /* Note, these probably should be in shared memory so that 
36  * they are truly global for all processes
37  */
38 extern struct s_shm *shm;             /* shared memory structure */
39 extern int  FiledDataChan;            /* File daemon data channel (port) */
40
41
42 /* Responses sent to the File daemon */
43 static char OK_data[]    = "3000 OK data\n";
44 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
45
46
47 /* 
48  *  Read Data and send to File Daemon
49  *   Returns: 0 on failure
50  *            1 on success
51  */
52 int do_read_data(JCR *jcr) 
53 {
54    BSOCK *ds;
55    BSOCK *fd_sock = jcr->file_bsock;
56    int ok = TRUE;
57    DEVICE *dev;
58    DEV_RECORD rec;
59    DEV_BLOCK *block;
60    POOLMEM *hdr; 
61    SESSION_LABEL sessrec;              /* session record */
62    
63    Dmsg0(20, "Start read data.\n");
64
65    dev = jcr->device->dev;
66    memset(&sessrec, 0, sizeof(sessrec));
67
68    /* Tell File daemon we will send data */
69    bnet_fsend(fd_sock, OK_data);
70    Dmsg1(10, "bstored>filed: %s\n", fd_sock->msg);
71
72    ds = fd_sock;
73
74    if (!bnet_set_buffer_size(ds, MAX_NETWORK_BUFFER_SIZE, BNET_SETBUF_READ)) {
75       return 0;
76    }
77
78
79    Dmsg1(20, "Begin read device=%s\n", dev_name(dev));
80
81    block = new_block(dev);
82
83    create_vol_list(jcr);
84
85    Dmsg1(20, "Found %d volumes names to restore.\n", jcr->NumVolumes);
86
87    /* 
88     * Ready device for reading, and read records
89     */
90    if (!acquire_device_for_read(jcr, dev, block)) {
91       free_block(block);
92       free_vol_list(jcr);
93       return 0;
94    }
95
96    memset(&rec, 0, sizeof(rec));
97    rec.data = ds->msg;                /* use socket message buffer */
98    hdr = get_pool_memory(PM_MESSAGE);
99
100    /*
101     *   Read records, apply BSR filtering, and return any that are 
102     *    matched.
103     */
104    for ( ;ok; ) {
105       DEV_RECORD *record;             /* for reading label of multi-volumes */
106
107       if (job_cancelled(jcr)) {
108          ok = FALSE;
109          break;
110       }
111       /* Read Record */
112       Dmsg1(500, "Main read_record. rem=%d\n", rec.remainder);
113       if (!read_record(dev, block, &rec)) {
114          Dmsg1(500, "Main read record failed. rem=%d\n", rec.remainder);
115          if (dev->state & ST_EOT) {
116             if (rec.remainder) {
117                Dmsg0(500, "Not end of record.\n");
118             }
119             Dmsg2(90, "NumVolumes=%d CurVolume=%d\n", jcr->NumVolumes, jcr->CurVolume);
120             /*
121              * End Of Tape -- mount next Volume (if another specified)
122              */
123             if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) {
124                VOL_LIST *vol = jcr->VolList;
125                close_dev(dev);
126                jcr->CurVolume++;
127                for (int i=1; i<jcr->CurVolume; i++) {
128                   vol = vol->next;
129                }
130                strcpy(jcr->VolumeName, vol->VolumeName);
131                Dmsg1(000, "There is another volume %s.\n", jcr->VolumeName);
132                dev->state &= ~ST_READ; 
133                if (!acquire_device_for_read(jcr, dev, block)) {
134                   Emsg2(M_ERROR, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName);
135                   ok = FALSE;
136                   break;
137                }
138                record = new_record();
139                Dmsg1(500, "read record after new tape. rem=%d\n", record->remainder);
140                read_record(dev, block, record); /* read vol label */
141                dump_label_record(dev, record, 0);
142                free_record(record);
143                continue;
144             }
145             Dmsg0(90, "End of Device reached.\n");
146             break;                    /* End of Tape */
147          }
148          if (dev->state & ST_EOF) {
149             Dmsg0(90, "Got End of File. Trying again ...\n");
150             continue;                 /* End of File */
151          }
152
153          Jmsg2(jcr, M_FATAL, 0, "Read error on Record Header %s ERR=%s\n", dev_name(dev), strerror(errno));
154          ok = FALSE;
155          break;
156       }
157
158       /* Some sort of label? */ 
159       if (rec.FileIndex < 0) {
160          char *rtype;
161          memset(&sessrec, 0, sizeof(sessrec));
162          switch (rec.FileIndex) {
163             case PRE_LABEL:
164                rtype = "Fresh Volume Label";   
165                break;
166             case VOL_LABEL:
167                rtype = "Volume Label";
168                unser_volume_label(dev, &rec);
169                break;
170             case SOS_LABEL:
171                rtype = "Begin Session";
172                unser_session_label(&sessrec, &rec);
173                break;
174             case EOS_LABEL:
175                rtype = "End Session";
176                break;
177             case EOM_LABEL:
178                rtype = "End of Media";
179                break;
180             default:
181                rtype = "Unknown";
182                break;
183          }
184          if (debug_level > 0) {
185             printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
186                rtype, rec.VolSessionId, rec.VolSessionTime, rec.Stream, rec.data_len);
187          }
188
189          Dmsg1(40, "Got label = %d\n", rec.FileIndex);
190          if (rec.FileIndex == EOM_LABEL) { /* end of tape? */
191             Dmsg0(40, "Get EOM LABEL\n");
192             break;                         /* yes, get out */
193          }
194          continue;                         /* ignore other labels */
195       } /* end if label record */
196
197       if (jcr->bsr) {
198          /* Match BSR against current record */
199          if (!match_bsr(jcr->bsr, &rec, &dev->VolHdr, &sessrec)) {
200             Dmsg0(50, "BSR rejected record\n");
201             continue;
202          }
203       } else { 
204          /* Old way, deprecated */
205          if (rec.VolSessionId != jcr->read_VolSessionId ||
206              rec.VolSessionTime != jcr->read_VolSessionTime) {
207             Dmsg0(50, "Ignore record ids not equal\n");
208             continue;                    /* ignore */
209          }
210       }
211        
212       /* Generate Header parameters and send to File daemon
213        * Note, we build header in hdr buffer to avoid wiping
214        * out the data record
215        */
216       ds->msg = hdr;
217       if (!bnet_fsend(ds, rec_header, rec.VolSessionId, rec.VolSessionTime,
218              rec.FileIndex, rec.Stream, rec.data_len)) {
219          Dmsg1(30, ">filed: Error Hdr=%s\n", ds->msg);
220          ds->msg = rec.data;
221          ok = FALSE;
222          break;
223       } else {
224          Dmsg1(30, ">filed: Hdr=%s\n", ds->msg);
225       }
226
227       ds->msg = rec.data;             /* restore data record address */
228
229       /* Send data record to File daemon */
230       ds->msglen = rec.data_len;
231       Dmsg1(40, ">filed: send %d bytes data.\n", ds->msglen);
232       if (!bnet_send(ds)) {
233          Dmsg0(0, "Error sending to FD\n");
234          Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
235             bnet_strerror(ds));
236          ok = FALSE;
237       }
238    }
239    /* Send end of data to FD */
240    bnet_sig(ds, BNET_EOF);
241
242    if (!release_device(jcr, dev, block)) {
243       ok = FALSE;
244    }
245    free_pool_memory(hdr);
246    free_block(block);
247    free_vol_list(jcr);
248    Dmsg0(30, "Done reading.\n");
249    return ok ? 1 : 0;
250 }