]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/spool.c
d825963e1cf5e01faff04638c23fb91496ad3939
[bacula/bacula] / bacula / src / stored / spool.c
1 /*
2  *  Spooling code 
3  *
4  *      Kern Sibbald, March 2004
5  *
6  *  Version $Id$
7  */
8 /*
9    Copyright (C) 2000-2004 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 static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name);
33 static int open_data_spool_file(JCR *jcr);
34 static int close_data_spool_file(JCR *jcr);
35 static bool despool_data(DCR *dcr);
36
37
38 int begin_data_spool(JCR *jcr)
39 {
40    if (jcr->dcr->spool_data) {
41       return open_data_spool_file(jcr);
42    }
43    return 1;
44 }
45
46 int discard_data_spool(JCR *jcr)
47 {
48    if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
49       return close_data_spool_file(jcr);
50    }
51    return 1;
52 }
53
54 int commit_data_spool(JCR *jcr)
55 {
56    bool stat;
57    if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
58       lock_device(jcr->dcr->dev);
59       stat = despool_data(jcr->dcr);
60       unlock_device(jcr->dcr->dev);
61       if (!stat) {
62          close_data_spool_file(jcr);
63          return 0;
64       }
65       return close_data_spool_file(jcr);
66    }
67    return 1;
68 }
69
70 static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name)
71 {
72    Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name,
73       jcr->Job, jcr->device->hdr.name);
74 }
75
76
77 static int open_data_spool_file(JCR *jcr)
78 {
79    POOLMEM *name  = get_pool_memory(PM_MESSAGE);
80    int spool_fd;
81
82    make_unique_data_spool_filename(jcr, &name);
83    if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) {
84       jcr->dcr->spool_fd = spool_fd;
85       jcr->spool_attributes = true;
86    } else {
87       Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno));
88       free_pool_memory(name);
89       return 0;
90     }
91     free_pool_memory(name);
92     return 1;
93 }
94
95 static int close_data_spool_file(JCR *jcr)
96 {
97     POOLMEM *name  = get_pool_memory(PM_MESSAGE);
98
99     make_unique_data_spool_filename(jcr, &name);
100     close(jcr->dcr->spool_fd);
101     jcr->dcr->spool_fd = -1;
102     unlink(name);
103     free_pool_memory(name);
104     return 1;
105 }
106
107 static bool despool_data(DCR *dcr)
108 {
109    DEVICE *sdev;
110    DCR *sdcr;
111    dcr->spooling = false;
112    bool ok = true;
113    DEV_BLOCK *block = dcr->block;
114    JCR *jcr = dcr->jcr;
115
116    /* Set up a dev structure to read */
117    sdev = (DEVICE *)malloc(sizeof(DEVICE));
118    memset(sdev, 0, sizeof(DEVICE));
119    sdev->fd = dcr->spool_fd;
120    lseek(sdev->fd, 0, SEEK_SET); /* rewind */
121    sdcr = new_dcr(jcr, sdev);
122    for ( ; ok; ) {
123       if (job_canceled(jcr)) {
124          ok = false;
125          break;
126       }
127       if (!read_block_from_dev(jcr, sdev, block, CHECK_BLOCK_NUMBERS)) {
128          if (dev_state(sdev, ST_EOT)) {
129             break;
130          }
131          ok = false;
132          break;
133       }
134       if (!write_block_to_dev(dcr, block)) {
135          ok = false;
136          break;
137       }
138    }
139    lseek(sdev->fd, 0, SEEK_SET); /* rewind */
140    if (ftruncate(sdev->fd, 0) != 0) {
141       ok = false;
142    }
143    return ok;
144 }
145
146 /*
147  * Write a block to the spool file
148  *
149  *  Returns: true on success or EOT
150  *           false on hard error
151  */
152 bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block)
153 {
154    ssize_t stat = 0;
155    uint32_t wlen;                     /* length to write */
156    DEVICE *dev = dcr->dev;
157    int retry = 0;
158
159    ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
160
161    wlen = block->binbuf;
162    if (wlen <= WRITE_BLKHDR_LENGTH) {  /* Does block have data in it? */
163       Dmsg0(100, "return write_block_to_dev no data to write\n");
164       return true;
165    }
166    /* 
167     * Clear to the end of the buffer if it is not full,
168     *  and on tape devices, apply min and fixed blocking.
169     */
170    if (wlen != block->buf_len) {
171       uint32_t blen;                  /* current buffer length */
172
173       Dmsg2(200, "binbuf=%d buf_len=%d\n", block->binbuf, block->buf_len);
174       blen = wlen;
175
176       /* Adjust write size to min/max for tapes only */
177       if (dev->state & ST_TAPE) {
178          if (wlen < dev->min_block_size) {
179             wlen =  ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
180          }
181          /* check for fixed block size */
182          if (dev->min_block_size == dev->max_block_size) {
183             wlen = block->buf_len;    /* fixed block size already rounded */
184          }
185       }
186       if (wlen-blen > 0) {
187          memset(block->bufp, 0, wlen-blen); /* clear garbage */
188       }
189    }  
190
191    ser_block_header(block);
192
193    Dmsg1(300, "Write block of %u bytes\n", wlen);      
194 write_again:
195    stat = write(dcr->spool_fd, block->buf, (size_t)wlen);
196    if (stat != (ssize_t)wlen) {
197       if (!despool_data(dcr)) {
198          return false;
199       }
200       if (retry++ > 1) {
201          return false;
202       }
203       goto write_again;
204    }
205
206    empty_block(block);
207    return true;
208 }
209
210
211
212 bool are_attributes_spooled(JCR *jcr)
213 {
214    return jcr->spool_attributes && jcr->dir_bsock->spool_fd;
215 }
216
217 int begin_attribute_spool(JCR *jcr)
218 {
219    if (!jcr->no_attributes && jcr->spool_attributes) {
220       return open_spool_file(jcr, jcr->dir_bsock);
221    }
222    return 1;
223 }
224
225 int discard_attribute_spool(JCR *jcr)
226 {
227    if (are_attributes_spooled(jcr)) {
228       return close_spool_file(jcr, jcr->dir_bsock);
229    }
230    return 1;
231 }
232
233 int commit_attribute_spool(JCR *jcr)
234 {
235    if (are_attributes_spooled(jcr)) {
236       bnet_despool_to_bsock(jcr->dir_bsock);
237       return close_spool_file(jcr, jcr->dir_bsock);
238    }
239    return 1;
240 }