]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/read.c
59851434f0d15a2f4609735020d77abf3373e33f
[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
84    create_vol_list(jcr);
85
86    Dmsg1(20, "Found %d volumes names to restore.\n", jcr->NumVolumes);
87
88    /* 
89     * Ready device for reading, and read records
90     */
91    if (!acquire_device_for_read(jcr, dev, block)) {
92       free_block(block);
93       free_vol_list(jcr);
94       return 0;
95    }
96
97    rec = new_record();
98    free_pool_memory(rec->data);
99    rec->data = ds->msg;                /* use socket message buffer */
100    hdr = get_pool_memory(PM_MESSAGE);
101
102    /*
103     *   Read records, apply BSR filtering, and return any that are 
104     *    matched.
105     */
106    for ( ;ok; ) {
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
114       if (!read_block_from_device(dev, block)) {
115          Dmsg1(500, "Main read record failed. rem=%d\n", rec->remainder);
116          if (dev->state & ST_EOT) {
117             if (!mount_next_read_volume(jcr, dev, block)) {
118                break;
119             }
120             continue;
121          }
122          if (dev->state & ST_EOF) {
123             Dmsg0(90, "Got End of File. Trying again ...\n");
124             continue;                 /* End of File */
125          }
126          if (dev->state & ST_SHORT) {
127             continue;
128          }
129       }
130
131       for (rec->state=0; !is_block_empty(rec); ) {
132
133          if (!read_record_from_block(block, rec)) {
134             break;
135          }
136          /*
137           * At this point, we have at least a record header.
138           *  Now decide if we want this record or not, but remember
139           *  before accessing the record, we may need to read again to
140           *  get all the data.
141           */
142
143          /* Some sort of label? */ 
144          if (rec->FileIndex < 0) {
145             char *rtype;
146             memset(&sessrec, 0, sizeof(sessrec));
147             switch (rec->FileIndex) {
148                case PRE_LABEL:
149                   rtype = "Fresh Volume Label";   
150                   break;
151                case VOL_LABEL:
152                   rtype = "Volume Label";
153                   unser_volume_label(dev, rec);
154                   break;
155                case SOS_LABEL:
156                   rtype = "Begin Session";
157                   unser_session_label(&sessrec, rec);
158                   break;
159                case EOS_LABEL:
160                   rtype = "End Session";
161                   break;
162                case EOM_LABEL:
163                   rtype = "End of Media";
164                   break;
165                default:
166                   rtype = "Unknown";
167                   break;
168             }
169             Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
170                   rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
171
172             Dmsg1(40, "Got label = %d\n", rec->FileIndex);
173             if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
174                Dmsg0(40, "Get EOM LABEL\n");
175                rec->remainder = 0;
176                break;                         /* yes, get out */
177             }
178             rec->remainder = 0;
179             continue;                         /* ignore other labels */
180          } /* end if label record */
181
182          /* Match BSR against current record */
183          if (jcr->bsr) {
184             if (!match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec)) {
185                Dmsg0(50, "BSR rejected record\n");
186                rec->remainder = 0;
187                continue;
188             }
189          } else { 
190             /* Old way, deprecated */
191             if (rec->VolSessionId != jcr->read_VolSessionId ||
192                 rec->VolSessionTime != jcr->read_VolSessionTime) {
193                Dmsg0(50, "Ignore record ids not equal\n");
194                rec->remainder = 0;
195                continue;                    /* ignore */
196             }
197          }
198
199          if (is_partial_record(rec)) {
200             break;                    /* Go read full record */
201          }
202           
203          /* Generate Header parameters and send to File daemon
204           * Note, we build header in hdr buffer to avoid wiping
205           * out the data record
206           */
207          ds->msg = hdr;
208          if (!bnet_fsend(ds, rec_header, rec->VolSessionId, rec->VolSessionTime,
209                 rec->FileIndex, rec->Stream, rec->data_len)) {
210             Dmsg1(30, ">filed: Error Hdr=%s\n", ds->msg);
211             hdr = ds->msg;
212             ds->msg = rec->data;
213             ok = FALSE;
214             break;
215          } else {
216             Dmsg1(30, ">filed: Hdr=%s\n", ds->msg);
217          }
218
219          hdr = ds->msg;               /* restore hdr buffer */
220          ds->msg = rec->data;         /* restore data record address */
221
222          /* Send data record to File daemon */
223          ds->msglen = rec->data_len;
224          Dmsg1(40, ">filed: send %d bytes data.\n", ds->msglen);
225          if (!bnet_send(ds)) {
226             Dmsg0(0, "Error sending to FD\n");
227             Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
228                bnet_strerror(ds));
229             ok = FALSE;
230          }
231       }
232    }
233    /* Send end of data to FD */
234    bnet_sig(ds, BNET_EOD);
235
236    if (!release_device(jcr, dev, block)) {
237       ok = FALSE;
238    }
239    free_pool_memory(hdr);
240    free_block(block);
241    rec->data = NULL;                  /* previously released */
242    free_record(rec);
243    free_vol_list(jcr);
244    Dmsg0(30, "Done reading.\n");
245    return ok ? 1 : 0;
246 }