4 * Kern Sibbald, March 2004
9 Copyright (C) 2000-2004 Kern Sibbald and John Walker
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.
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.
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,
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 static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block);
50 int begin_data_spool(JCR *jcr)
53 if (jcr->spool_data) {
54 Dmsg0(100, "Turning on data spooling\n");
55 jcr->dcr->spool_data = true;
56 stat = open_data_spool_file(jcr);
58 jcr->dcr->spooling = true;
64 int discard_data_spool(JCR *jcr)
66 if (jcr->dcr->spooling) {
67 Dmsg0(100, "Data spooling discarded\n");
68 return close_data_spool_file(jcr);
73 int commit_data_spool(JCR *jcr)
76 if (jcr->dcr->spooling) {
77 Dmsg0(100, "Committing spooled data\n");
78 stat = despool_data(jcr->dcr);
80 Dmsg1(000, "Bad return from despool WroteVol=%d\n", jcr->dcr->WroteVol);
81 close_data_spool_file(jcr);
84 return close_data_spool_file(jcr);
89 static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name)
91 Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name,
92 jcr->Job, jcr->device->hdr.name);
96 static int open_data_spool_file(JCR *jcr)
98 POOLMEM *name = get_pool_memory(PM_MESSAGE);
101 make_unique_data_spool_filename(jcr, &name);
102 if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) {
103 jcr->dcr->spool_fd = spool_fd;
104 jcr->spool_attributes = true;
106 Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno));
107 free_pool_memory(name);
110 Dmsg1(100, "Created spool file: %s\n", name);
111 free_pool_memory(name);
115 static int close_data_spool_file(JCR *jcr)
117 POOLMEM *name = get_pool_memory(PM_MESSAGE);
119 make_unique_data_spool_filename(jcr, &name);
120 close(jcr->dcr->spool_fd);
121 jcr->dcr->spool_fd = -1;
122 jcr->dcr->spooling = false;
124 Dmsg1(100, "Deleted spool file: %s\n", name);
125 free_pool_memory(name);
129 static bool despool_data(DCR *dcr)
133 dcr->spooling = false;
139 // lock_device(dcr->dev);
140 Dmsg0(100, "Despooling data\n");
141 /* Set up a dev structure to read */
142 rdev = (DEVICE *)malloc(sizeof(DEVICE));
143 memset(rdev, 0, sizeof(DEVICE));
144 rdev->dev_name = get_memory(strlen("spool")+1);
145 strcpy(rdev->dev_name, "spool");
146 rdev->errmsg = get_pool_memory(PM_EMSG);
148 rdcr = new_dcr(NULL, rdev);
149 rdcr->spool_fd = dcr->spool_fd;
150 rdcr->jcr = jcr; /* set a valid jcr */
152 lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
154 if (job_canceled(jcr)) {
158 stat = read_block_from_spool_file(rdcr, block);
159 if (stat == RB_EOT) {
161 } else if (stat == RB_ERROR) {
165 ok = write_block_to_device(dcr, block);
166 Dmsg3(100, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex);
168 lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
169 if (ftruncate(rdcr->spool_fd, 0) != 0) {
170 Dmsg1(000, "Bad return from ftruncate. ERR=%s\n", strerror(errno));
173 free_memory(rdev->dev_name);
174 free_pool_memory(rdev->errmsg);
178 // unlock_device(dcr->dev);
183 * Read a block from the spool file
185 * Returns RB_OK on success
186 * RB_EOT when file done
189 static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block)
196 stat = read(dcr->spool_fd, (char *)&hdr, (size_t)rlen);
198 Dmsg0(100, "EOT on spool read.\n");
200 } else if (stat != (ssize_t)rlen) {
202 Jmsg(dcr->jcr, M_FATAL, 0, "Spool read error. ERR=%s\n", strerror(errno));
204 Dmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat);
205 Jmsg2(dcr->jcr, M_FATAL, 0, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat);
210 if (rlen > block->buf_len) {
211 Dmsg2(000, "Spool block too big. Max %u bytes, got %u\n", block->buf_len, rlen);
212 Jmsg2(dcr->jcr, M_FATAL, 0, "Spool block too big. Max %u bytes, got %u\n", block->buf_len, rlen);
215 stat = read(dcr->spool_fd, (char *)block->buf, (size_t)rlen);
216 if (stat != (ssize_t)rlen) {
217 Dmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat);
218 Jmsg2(dcr->jcr, M_FATAL, 0, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat);
221 /* Setup write pointers */
222 block->binbuf = rlen;
223 block->bufp = block->buf + block->binbuf;
224 block->FirstIndex = hdr.FirstIndex;
225 block->LastIndex = hdr.LastIndex;
226 block->VolSessionId = dcr->jcr->VolSessionId;
227 block->VolSessionTime = dcr->jcr->VolSessionTime;
228 Dmsg2(400, "Read block FI=%d LI=%d\n", block->FirstIndex, block->LastIndex);
233 * Write a block to the spool file
235 * Returns: true on success or EOT
236 * false on hard error
238 bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block)
241 uint32_t wlen; /* length to write */
245 ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
247 if (block->binbuf <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
248 Dmsg0(100, "return write_block_to_dev no data to write\n");
252 hdr.FirstIndex = block->FirstIndex;
253 hdr.LastIndex = block->LastIndex;
254 hdr.len = block->binbuf;
257 stat = write(dcr->spool_fd, (char*)&hdr, (size_t)wlen);
258 if (stat != (ssize_t)wlen) {
259 if (!despool_data(dcr)) {
265 goto write_hdr_again;
269 wlen = block->binbuf;
270 Dmsg2(300, "Wrote block FI=%d LI=%d\n", block->FirstIndex, block->LastIndex);
272 stat = write(dcr->spool_fd, block->buf, (size_t)wlen);
273 if (stat != (ssize_t)wlen) {
274 if (!despool_data(dcr)) {
289 bool are_attributes_spooled(JCR *jcr)
291 return jcr->spool_attributes && jcr->dir_bsock->spool_fd;
294 int begin_attribute_spool(JCR *jcr)
296 if (!jcr->no_attributes && jcr->spool_attributes) {
297 return open_spool_file(jcr, jcr->dir_bsock);
302 int discard_attribute_spool(JCR *jcr)
304 if (are_attributes_spooled(jcr)) {
305 return close_spool_file(jcr, jcr->dir_bsock);
310 int commit_attribute_spool(JCR *jcr)
312 if (are_attributes_spooled(jcr)) {
313 bnet_despool_to_bsock(jcr->dir_bsock);
314 return close_spool_file(jcr, jcr->dir_bsock);