rtcpd_Tape.c 110 KB
Newer Older
Olof Barring's avatar
Olof Barring committed
1
/*
2
 * Copyright (C) 1999-2004 by CERN IT
Olof Barring's avatar
Olof Barring committed
3
4
5
6
 * All rights reserved
 */

/*
7
 * rtcpd_Tape.c - RTCOPY server tape IO thread
Olof Barring's avatar
Olof Barring committed
8
9
 */

10
11
#include <stdlib.h>
#include <time.h>
Olof Barring's avatar
Olof Barring committed
12
13
14
15
16
#include <sys/param.h>
#include <sys/types.h>                  /* Standard data types          */
#include <netdb.h>                      /* Network "data base"          */
#include <sys/socket.h>
#include <netinet/in.h>                 /* Internet data types          */
17
#include <sys/time.h>
Benjamin Couturier's avatar
Benjamin Couturier committed
18
#include <sys/times.h>
Olof Barring's avatar
Olof Barring committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#include <errno.h>
#include <stdarg.h>
#include <sys/stat.h>

#include <pwd.h>
#include <Castor_limits.h>
#include <Cglobals.h>
#include <log.h>
#include <osdep.h>
#include <net.h>
#include <Cthread_api.h>
#include <vdqm_api.h>
#include <Ctape_api.h>
33
#include <Cuuid.h>
Olof Barring's avatar
Olof Barring committed
34
35
36
37
#include <rtcp_constants.h>
#include <rtcp.h>
#include <rtcp_server.h>
#include <serrno.h>
38
#include "tplogger_api.h"
39
char *getconfent (char *, char *, int);
Olof Barring's avatar
Olof Barring committed
40

41
#include "h/tapeBridgeClientInfo2MsgBody.h"
42
#include "h/tapebridge_constants.h"
43
44
#include "h/tapebridge_recvTapeBridgeFlushedToTapeAck.h"
#include "h/tapebridge_sendTapeBridgeFlushedToTape.h"
45
#include "h/tapebridge_tapeFlushModeToStr.h"
Benjamin Couturier's avatar
Benjamin Couturier committed
46

47
#include <fcntl.h>
48
#include <stdint.h>
49
50
#include <sys/types.h>
#include <sys/stat.h>
51

Olof Barring's avatar
Olof Barring committed
52
53
#define TP_STATUS(X) (proc_stat.tapeIOstatus.current_activity = (X))
#define TP_SIZE(X)   (proc_stat.tapeIOstatus.nbbytes += (u_signed64)(X))
54
#define DEBUG_PRINT(X) {if ( debug == TRUE ) rtcp_log X ;}
Olof Barring's avatar
Olof Barring committed
55
56

typedef struct thread_arg {
57
    int client_socket;
Olof Barring's avatar
Olof Barring committed
58
    tape_list_t *tape;
59
    rtcpClientInfo_t *client;
60

61
62
63
64
65
    /**
     * Boolean value specifying whether or not the client of the rtcpd daemon is
     * tapebridged.
     */
    int clientIsTapeBridge;
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    /**
     * The mode of tape-flush behaviour to be used when writing to tape.
     *
     * TAPEBRIDGE_N_FLUSHES_PER_FILE
     * TAPEBRIDGE_ONE_FLUSH_PER_N_FILES
     */
    uint32_t tapeFlushMode;

    /**
     * The maximum number of bytes to be written to tape before a flush to
     * tape.
     *
     * The value of maxBytesBeforeFlush is only applicable if tapeFlushMode is
     * TAPEBRIDGE_ONE_FLUSH_PER_N_FILES.
     */
82
83
    uint64_t maxBytesBeforeFlush;

84
85
86
87
88
89
90
    /**
     * The maximum number of files to be written to tape before a flush to
     * tape.
     *
     * The value of maxFilesBeforeFlush is only applicable if tapeFlushMode is
     * TAPEBRIDGE_ONE_FLUSH_PER_N_FILES.
     */
91
    uint64_t maxFilesBeforeFlush;
92
93
94
95
96
97
98
99

    /**
     * Pointer to a boolean indicating whether or not the tape still needs to
     * be released from the drive after all of the work of rtcpd has been
     * finished, in other words after the client has sent the "end of entire
     * session" message (RTCP_ENDOF_REQ) on the main socket.
     */
    int *tapeNeedsToBeReleasedAtEndOfSession;
Olof Barring's avatar
Olof Barring committed
100
101
} thread_arg_t;

102
103
extern int Debug;

Olof Barring's avatar
Olof Barring committed
104
105
106
107
108
109
110
111
112
113
114
115
116
extern int nb_bufs;

extern int bufsz;

extern processing_cntl_t proc_cntl;
extern processing_status_t proc_stat;

extern buffer_table_t **databufs;

extern rtcpClientInfo_t *client;

extern int success;
extern int failure;
117
extern int AbortFlag;
Olof Barring's avatar
Olof Barring committed
118
119

static int last_block_done = 0;
120
static int WaitToJoin = FALSE;
Olof Barring's avatar
Olof Barring committed
121

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
 * Signal to disk IO thread that file has been positioned (tape read with
 * stager only).
 */
int rtcpd_SignalFilePositioned(tape_list_t *tape, file_list_t *file) {
    int rc;

    rtcp_log(LOG_DEBUG,"rtcpd_SignalFilePositioned() called\n");
    tl_rtcpd.tl_log( &tl_rtcpd, 11, 2, 
                     "func"   , TL_MSG_PARAM_STR, "rtcpd_SignalFilePositioned",
                     "Message", TL_MSG_PARAM_STR, "called" );
    if ( tape == NULL || file == NULL ) {
        serrno = EINVAL;
        return(-1);
    }

    rc = Cthread_mutex_lock_ext(proc_cntl.cntl_lock);
    if ( rc == -1 ) {
        rtcp_log(LOG_ERR,"rtcpd_SignalFilePositioned(): Cthread_mutex_lock_ext(proc_cntl): %s\n",
            sstrerror(serrno));
        tl_rtcpd.tl_log( &tl_rtcpd, 11, 3, 
                         "func"   , TL_MSG_PARAM_STR, "rtcpd_SignalFilePositioned",
                         "Message", TL_MSG_PARAM_STR, "Cthread_mutex_lock_ext(proc_cntl)",
                         "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno) );        
        return(-1);
    }
    rc = Cthread_cond_broadcast_ext(proc_cntl.cntl_lock);
    if ( rc == -1 ) {
        rtcp_log(LOG_ERR,"rtcpd_SignalFilePositioned(): Cthread_cond_broadcast_ext(proc_cntl): %s\n",
            sstrerror(serrno));
        tl_rtcpd.tl_log( &tl_rtcpd, 11, 3, 
                         "func"   , TL_MSG_PARAM_STR, "rtcpd_SignalFilePositioned",
                         "Message", TL_MSG_PARAM_STR, "Cthread_cond_broadcast_ext(proc_cntl)",
                         "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno) );                
        (void)Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
        return(-1);
    }
    rc = Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
    if ( rc == -1 ) {
        rtcp_log(LOG_ERR,"rtcpd_SignalFilePositioned(): Cthread_mutex_unlock_ext(proc_cntl): %s\n",
                 sstrerror(serrno));
        tl_rtcpd.tl_log( &tl_rtcpd, 11, 3, 
                         "func"   , TL_MSG_PARAM_STR, "rtcpd_SignalFilePositioned",
                         "Message", TL_MSG_PARAM_STR, "Cthread_mutex_unlock_ext(proc_cntl)",
                         "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno) );                        
        return(-1);
    }
    rtcp_log(LOG_DEBUG,"rtcpd_SignalFilePositioned() returns\n");
    tl_rtcpd.tl_log( &tl_rtcpd, 11, 2, 
                     "func"   , TL_MSG_PARAM_STR, "rtcpd_SignalFilePositioned",
                     "Message", TL_MSG_PARAM_STR, "returns" );
    return(0);
}

176
177
178
179
180
181
182
183
static int WaitDiskIO() {
    int rc;

    rc = Cthread_mutex_lock_ext(proc_cntl.cntl_lock);
    if ( rc == -1 ) return(-1);

    rtcp_log(LOG_DEBUG,"WaitDiskIO(): diskIOfinished=%d, nb_diskIOactive=%d\n",
             proc_cntl.diskIOfinished,proc_cntl.nb_diskIOactive);
184
185
186
187
    tl_rtcpd.tl_log( &tl_rtcpd, 11, 3, 
                     "func"           , TL_MSG_PARAM_STR, "WaitDiskIO",
                     "diskIOfinished" , TL_MSG_PARAM_INT, proc_cntl.diskIOfinished,
                     "nb_diskIOactive", TL_MSG_PARAM_INT, proc_cntl.nb_diskIOactive );
188
189
190
191
192
    while ( proc_cntl.diskIOfinished == 0 || proc_cntl.nb_diskIOactive > 0 ) {
        rc = Cthread_cond_wait_ext(proc_cntl.cntl_lock);
        if ( rc == -1 ) return(-1);
        rtcp_log(LOG_DEBUG,"WaitDiskIO(): diskIOfinished=%d, nb_diskIOactive=%d\n",
                 proc_cntl.diskIOfinished,proc_cntl.nb_diskIOactive);
193
194
195
196
        tl_rtcpd.tl_log( &tl_rtcpd, 11, 3, 
                         "func"           , TL_MSG_PARAM_STR, "WaitDiskIO",
                         "diskIOfinished" , TL_MSG_PARAM_INT, proc_cntl.diskIOfinished,
                         "nb_diskIOactive", TL_MSG_PARAM_INT, proc_cntl.nb_diskIOactive );
197
198
199
200
201
    }
    rc = Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
    return(rc);
}

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
static void TapeIOstarted() {
    (void)Cthread_mutex_lock_ext(proc_cntl.cntl_lock);
    proc_cntl.tapeIOstarted = 1;
    proc_cntl.tapeIOfinished = 0;
    (void)Cthread_cond_broadcast_ext(proc_cntl.cntl_lock);
    (void)Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
    return;
}

static void TapeIOfinished() {
    (void)Cthread_mutex_lock_ext(proc_cntl.cntl_lock);
    proc_cntl.tapeIOstarted = 0;
    proc_cntl.tapeIOfinished = 1;
    (void)Cthread_cond_broadcast_ext(proc_cntl.cntl_lock);
    (void)Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
    return;
}

220
221
222
223
224
225
226
227
228
int rtcpd_nbFullBufs(int increment) {
    int rc;
    (void)Cthread_mutex_lock_ext(proc_cntl.cntl_lock);
    proc_cntl.nbFullBufs += increment;
    rc = proc_cntl.nbFullBufs;
    (void)Cthread_cond_broadcast_ext(proc_cntl.cntl_lock);
    (void)Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
    return(rc);
}
229

Olof Barring's avatar
Olof Barring committed
230
231
232
/*
 * Read from tape to memory
 */
233
234
235
236
237
238
239
240
241
242
243
244
static int MemoryToTape(
    const int          tape_fd,
    int *const         indxp,
    int *const         firstblk,
    int *const         diskIOfinished,
    tape_list_t *const tape, 
    file_list_t *const file,
    const uint32_t     tapeFlushMode,
    uint64_t *const    nbBytesWrittenWithoutFlush,
    uint64_t *const    nbFilesWrittenWithoutFlush,
    const uint64_t     maxBytesBeforeFlush,
    const uint64_t     maxFilesBeforeFlush,
245
    int *const         flushedToTapeAfterNFiles,
246
    uint64_t *const    batchBytesToTape) {
247
248
    int rc = 0;
    int nb_bytes, i, j, last_sz, blksiz, severity, lrecl;
249
    int end_of_tpfile, buf_done, nb_truncated, spill, bytes_used, proc_err;
250
    int pileupWaitTime = 0, nbFullBufs;
251
252
    char *convert_buffer = NULL;
    void *convert_context = NULL;
253
    char *p;
254
255
    register int Uformat;
    register int debug = Debug;
256
    register int convert, NoSyncAccess;
Olof Barring's avatar
Olof Barring committed
257
258
259
260
    rtcpTapeRequest_t *tapereq = NULL;
    rtcpFileRequest_t *filereq = NULL;

    if ( tape_fd < 0 || indxp == NULL || firstblk == NULL ||
261
         diskIOfinished == NULL || tape == NULL || file == NULL ) {
Olof Barring's avatar
Olof Barring committed
262
263
264
265
266
267
268
        serrno = EINVAL;
        return(-1);
    }
    tapereq = &tape->tapereq;
    filereq = &file->filereq;
    if ( last_block_done != 0 ) {
        rtcp_log(LOG_ERR,"MemoryToTape() called beyond last block!!!\n");
269
270
271
        tl_rtcpd.tl_log( &tl_rtcpd, 3, 2, 
                         "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                         "Message", TL_MSG_PARAM_STR, "called beyond last block" );
Olof Barring's avatar
Olof Barring committed
272
273
274
275
276
        return(-1);
    }

    blksiz = filereq->blocksize;
    lrecl = filereq->recordlength;
277
278
    Uformat = (*filereq->recfm == 'U' ? TRUE : FALSE);
    if ( (lrecl <= 0) && (Uformat == FALSE) ) lrecl = blksiz;
279
280
281
282
    else if ( Uformat == TRUE ) lrecl = 0;

    convert = filereq->convert;
    nb_truncated = spill = 0;
283
    NoSyncAccess = *diskIOfinished;
284

285
286
287
288
    if ( ((p = getenv("RTCPD_PILEUP_WAIT_TIME")) != NULL) ||
         ((p = getconfent("RTCPD","PILEUP_WAIT_TIME",0)) != NULL) )
      pileupWaitTime = atoi(p);

Olof Barring's avatar
Olof Barring committed
289
290
291
292
    /*
     * Write loop to break out of
     */
    end_of_tpfile = FALSE;
293
    proc_err = 0;
Olof Barring's avatar
Olof Barring committed
294
295
296
297
298
299
    for (;;) {
        i = *indxp;
        buf_done = FALSE;
        /*
         * Synchronize access to next buffer
         */
300
        if ( NoSyncAccess == 0 ) {
301
302
303
304
305
306
307
308
            TP_STATUS(RTCP_PS_WAITMTX);
            nbFullBufs = rtcpd_nbFullBufs(0);
            TP_STATUS(RTCP_PS_WAITMTX);
            if ( (nbFullBufs < 1) && (pileupWaitTime > 0) ) {
              rtcp_log(LOG_INFO,"Tape IO protection against disk IO slack: index=%d, nb full buffers=%d, wait %d seconds\n",
                       i,
                       nbFullBufs,
                       pileupWaitTime);
309
310
311
312
313
314
              tl_rtcpd.tl_log( &tl_rtcpd, 10, 5, 
                               "func"           , TL_MSG_PARAM_STR, "MemoryToTape",
                               "Message"        , TL_MSG_PARAM_STR, "Tape IO protection against disk IO slack",
                               "index"          , TL_MSG_PARAM_INT, i,
                               "nb full buffers", TL_MSG_PARAM_INT, nbFullBufs,
                               "wait seconds"   , TL_MSG_PARAM_INT, pileupWaitTime );
315
              rtcp_log(LOG_INFO,"path=%s\n",filereq->file_path);
316
317
318
              tl_rtcpd.tl_log( &tl_rtcpd, 10, 2, 
                               "func", TL_MSG_PARAM_STR, "MemoryToTape",
                               "path", TL_MSG_PARAM_STR, filereq->file_path);
319
320
              sleep(pileupWaitTime);
            }
321
322
323
324
325
326
            TP_STATUS(RTCP_PS_WAITMTX);
            rc = Cthread_mutex_lock_ext(databufs[i]->lock);
            TP_STATUS(RTCP_PS_NOBLOCKING);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() Cthread_mutex_lock_ext(): %s\n",
                    sstrerror(serrno));
327
328
329
330
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"    , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message" , TL_MSG_PARAM_STR, "Cthread_mutex_lock_ext",
                                 "Error"   , TL_MSG_PARAM_STR, sstrerror(serrno));
331
332
333
334
335
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
                return(-1);
336
            }
Olof Barring's avatar
Olof Barring committed
337
338
339
340
341
        }
        /*
         * Wait until it is full
         */
        while (databufs[i]->flag == BUFFER_EMPTY) {
342
343
            rtcpd_CheckReqStatus(NULL,file,NULL,&severity);
            if ( (proc_err = ((severity | rtcpd_CheckProcError()) & 
344
                  RTCP_FAILED)) != 0 ) {
345
346
347
348
349
350
351
352
353
354
355
                (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                    convert_buffer = NULL;
                    convert_context = NULL;
                }
                break;
            }

356
357
            if ( NoSyncAccess == 1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() unexpected empty buffer %d after diskIO finished\n",i);
358
359
360
361
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "unexpected empty buffer after diskIO finished",
                                 "buffer" , TL_MSG_PARAM_INT, i );
362
363
364
365
366
367
                (void)rtcpd_SetReqStatus(NULL,file,SEINTERNAL,
                                         RTCP_FAILED|RTCP_UNERR);
                (void)rtcpd_AppendClientMsg(NULL,file,"Internal error: %s\n",
                                           "unexpected empty buffer");
                return(-1);
            }
368
            databufs[i]->nb_waiters++;
Olof Barring's avatar
Olof Barring committed
369
370
371
372
373
374
            TP_STATUS(RTCP_PS_WAITCOND);
            rc = Cthread_cond_wait_ext(databufs[i]->lock);
            TP_STATUS(RTCP_PS_NOBLOCKING);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() Cthread_cond_wait_ext(): %s\n",
                    sstrerror(serrno));
375
376
377
378
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "Cthread_cond_wait_ext",
                                 "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
379
380
381
382
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
Olof Barring's avatar
Olof Barring committed
383
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
Olof Barring's avatar
Olof Barring committed
384
385
                return(-1);
            }
386
            databufs[i]->nb_waiters--;
387
388
389
        } /*  while (databufs[i]->flag == BUFFER_EMPTY) */

        if ( databufs[i]->flag == BUFFER_FULL ) {
390
            rtcpd_CheckReqStatus(NULL,file,NULL,&severity);
391
            if ( (proc_err = ((severity | rtcpd_CheckProcError()) & 
392
                  RTCP_FAILED)) != 0 ) {
Olof Barring's avatar
Olof Barring committed
393
394
                (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
395
396
397
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
398
399
                    convert_buffer = NULL;
                    convert_context = NULL;
400
                }
Olof Barring's avatar
Olof Barring committed
401
            }
402
        }
403
        if ( proc_err != 0 ) break;
404
        DEBUG_PRINT((LOG_DEBUG,"MemoryToTape() buffer %d full\n",i));
Olof Barring's avatar
Olof Barring committed
405
406
407
408
409
410

        /*
         * Verify that actual buffer size matches block size
         */
        if ( (databufs[i]->length % blksiz) != 0 ) {
            rtcp_log(LOG_ERR,"MemoryToTape() blocksize mismatch\n");
411
412
413
            tl_rtcpd.tl_log( &tl_rtcpd, 3, 2, 
                             "func"    , TL_MSG_PARAM_STR, "MemoryToTape",
                             "Messsage", TL_MSG_PARAM_STR, "blocksize mismatch" );
414
415
416
417
            if ( NoSyncAccess == 0 ) {
                (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
            }
418
419
420
421
            if ( (convert & FIXVAR) != 0 ) {
                if ( convert_buffer != NULL ) free(convert_buffer);
                if ( convert_context != NULL ) free(convert_context);
            }
422
423
424
425
            (void)rtcpd_SetReqStatus(NULL,file,SEINTERNAL,
                                     RTCP_FAILED|RTCP_UNERR);
            (void)rtcpd_AppendClientMsg(NULL,file,"Internal error: %s\n",
                                        "MemoryToTape() blocksize mismatch");
Olof Barring's avatar
Olof Barring committed
426
427
            return(-1);
        }
428
429
430
        if ( ((convert & FIXVAR) != 0) && (convert_buffer == NULL) ) {
            convert_buffer = (char *)malloc(blksiz);
            if ( convert_buffer == NULL ) {
431
                (void)rtcpd_SetReqStatus(NULL,file,errno, RTCP_FAILED);
432
433
434
                (void)rtcpd_AppendClientMsg(NULL,file,RT105,sstrerror(errno));
                rtcp_log(LOG_ERR,"MemoryToTape() malloc(): %s\n",
                    sstrerror(errno));
435
436
437
438
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "malloc",
                                 "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
Olof Barring's avatar
Olof Barring committed
439
                if ( NoSyncAccess == 0 ) {
440
441
442
                    (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                    (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
                }
443
444
445
                return(-1);
            }
        }
Olof Barring's avatar
Olof Barring committed
446
447
448
449
450
        /*
         * Check if this is the last buffer of the tape file
         */
        end_of_tpfile = databufs[i]->end_of_tpfile;
        if ( end_of_tpfile == TRUE ) 
451
            DEBUG_PRINT((LOG_DEBUG,"MemoryToTape() end of tape file in buffer %d\n",i));
Olof Barring's avatar
Olof Barring committed
452
453
454
455
        /*
         * Copy the data to tape
         */
        last_sz = 0;
456
        if ( filereq->maxnbrec > 0 && (convert & FIXVAR) == 0 ) {
Olof Barring's avatar
Olof Barring committed
457
458
459
460
            /*
             * Check if we reached the number of records limit
             * and, if so, reduce the data_length accordingly.
             */
461
462
463
464
465
            if ( Uformat == FALSE ) {
                if ( filereq->nbrecs + databufs[i]->data_length/lrecl >
                    filereq->maxnbrec ) {
                    databufs[i]->data_length = (int)(filereq->maxnbrec -
                        filereq->nbrecs) * lrecl;
466
                    rtcpd_SetReqStatus(NULL,file,ERTLIMBYSZ,RTCP_OK | RTCP_LIMBYSZ);
467
468
469
470
471
472
                }
            } else {
                if ( filereq->nbrecs + databufs[i]->nbrecs > 
                    filereq->maxnbrec ) {
                    databufs[i]->nbrecs = (int)(filereq->maxnbrec -
                        filereq->nbrecs);
473
                    rtcpd_SetReqStatus(NULL,file,ERTLIMBYSZ,RTCP_OK | RTCP_LIMBYSZ);
474
475
                }
            }
Olof Barring's avatar
Olof Barring committed
476
        }
477
478
        DEBUG_PRINT((LOG_DEBUG,"MemoryToTape() write %d bytes to tape\n",
            databufs[i]->data_length));
479
480
        j = *firstblk;
        for (;;) {
481
            if ( (Uformat == FALSE) || ((Uformat == TRUE) && (convert & NOF77CW) != 0) ) {
482
483
484
485
486
487
488
                /*
                 * Fix record format
                 */
                if ( (convert & FIXVAR) == 0 ) {
                    /*
                     * Have we read all data in this buffer yet?
                     */
489
490
491
492
493
494
                    if ( j*blksiz >= databufs[i]->data_length + 
                                     (*firstblk) * blksiz ) {
                        DEBUG_PRINT((LOG_DEBUG,"MemoryToTape() reached EOB (buffer %d), j=%d, blksiz=%d, data_length=%d, firstblk=%d\n",
                                i,j,blksiz,databufs[i]->data_length,*firstblk));
                        break;
                    }
495
496
497
498
                    /*
                     * Normal no record padding format.
                     * Note: last block of file may be partial.
                     */
499
                    nb_bytes = databufs[i]->data_length - (j-*firstblk)*blksiz;
500
501
502
503
504
505
506
507
508
509
510
511
512
                    if ( nb_bytes > blksiz ) nb_bytes = blksiz;
                    convert_buffer = databufs[i]->buffer + j*blksiz;
                } else {
                    /*
                     * Record padding (blocking) format: input records
                     * are normal text lines with newlines, output
                     * records are fixed length (lrecl) where the new
                     * line has been replaced with spaces (' ') padded
                     * up to lrecl
                     */
                    for (;;) {
                        nb_bytes = rtcpd_VarToFix(
                            databufs[i]->buffer + (*firstblk)*blksiz,
513
514
515
516
517
518
519
520
521
                            convert_buffer,
                            databufs[i]->data_length - (*firstblk)*blksiz,
                            blksiz,lrecl,&bytes_used,
                            &nb_truncated,&convert_context);

                        if ( nb_bytes > 0 ) filereq->nbrecs++;
                        if ( filereq->maxnbrec > 0 &&
                             filereq->nbrecs > filereq->maxnbrec ) {
                            spill = nb_bytes = 0;
522
                            rtcpd_SetReqStatus(NULL,file,ERTLIMBYSZ,RTCP_OK | 
523
524
525
526
                                                               RTCP_LIMBYSZ);
                            break;
                        }
                        file->tapebytes_sofar += (u_signed64)bytes_used;
527
528
529
530
531
532
533
534
535
536
537
538
539
                        if ( nb_bytes == blksiz ) {
                            spill = 0;
                            break;
                        } else if ( nb_bytes > 0 ) {
                            spill = nb_bytes;
                            nb_bytes = 0;
                        } else if ( nb_bytes <= 0 ) break;
                    }
                    /*
                     * Break out to get a new buffer
                     */
                    if ( nb_bytes <= 0 ) break;
                }
540
            } else {
541
542
543
544
545
                /*
                 * FORTRAN sequential access variable length records.
                 * Have we read all data in this buffer yet?
                 */
                if ( j*blksiz >= databufs[i]->data_length ) break;
546
                nb_bytes = databufs[i]->lrecl_table[j];
547
                convert_buffer = databufs[i]->buffer + j*blksiz;
548
            }
Olof Barring's avatar
Olof Barring committed
549

550
            if ( (convert & EBCCONV) != 0 ) asc2ebc(convert_buffer,nb_bytes);
Olof Barring's avatar
Olof Barring committed
551
552
553
554
555
            /*
             * >>>>>>>>>>> write to tape <<<<<<<<<<<<<
             */
            TP_STATUS(RTCP_PS_WRITE);
            rc = twrite(tape_fd,
556
                        convert_buffer,
Olof Barring's avatar
Olof Barring committed
557
558
                        nb_bytes,
                        tape,
559
560
                        file,
                        tapeFlushMode);
Olof Barring's avatar
Olof Barring committed
561
            TP_STATUS(RTCP_PS_NOBLOCKING);
Benjamin Couturier's avatar
Benjamin Couturier committed
562
563
            
	    if ( rc == -1 ) {
564
                rtcp_log(LOG_ERR,"MemoryToTape() tape write error\n");
565
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
566
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
567
568
                                 "Message", TL_MSG_PARAM_STR, "tape write error",
                                 "Drive"  , TL_MSG_PARAM_STR, tapereq->unit );
569
570
571
572
                if ( NoSyncAccess == 0 ) {
                    (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                    (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
                }
573
574
575
576
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
Olof Barring's avatar
Olof Barring committed
577
578
                return(-1);
            }
Benjamin Couturier's avatar
Benjamin Couturier committed
579
580

	    if ( rc == 0 ) {
Olof Barring's avatar
Olof Barring committed
581
582
583
584
585
586
587
                /*
                 * EOV reached
                 */
                if ( file->eovflag == 1 ) *firstblk = j;
                break;
            }
            last_sz += rc;
588
589
590
591
592
593
            if ( (convert & FIXVAR) == 0 ) {
                file->tapebytes_sofar += (u_signed64)rc;
                if ( lrecl > 0 && rc/lrecl > 0 ) 
                    filereq->nbrecs += (u_signed64)rc/lrecl;
                else if ( rc > 0 ) filereq->nbrecs++;
            }
Benjamin Couturier's avatar
Benjamin Couturier committed
594

Olof Barring's avatar
Olof Barring committed
595
            TP_SIZE(rc);
596
            j++;
Olof Barring's avatar
Olof Barring committed
597
        } /* End of for (j=...) */
598
599
        DEBUG_PRINT((LOG_DEBUG,"MemoryToTape() wrote %d bytes to tape\n",
            last_sz));
600
601
602
603
604
605
606
607
608
609
610
        /*
         * Subtract what we've just written. If we have reblocked
         * the data the last_sz is larger than the input data size
         * because records have been padded. In that case 
         * rtcpd_VarToFix() returns 0 if all input data has been
         * converted.
         */
        if ( (convert & FIXVAR) == 0 )
            databufs[i]->data_length -= last_sz;
        else
            if ( nb_bytes == 0 ) databufs[i]->data_length = 0;
Olof Barring's avatar
Olof Barring committed
611
612
613
614
615

        /*
         * Reset the buffer semaphore only if the
         * full buffer has been succesfully written.
         */
616
        if ( databufs[i]->data_length <= 0 ) {
Olof Barring's avatar
Olof Barring committed
617
618
619
620
621
            /*
             * Check if this is the request end.
             */
            last_block_done = databufs[i]->last_buffer;
            if ( last_block_done != 0 )
622
623
                DEBUG_PRINT((LOG_DEBUG,"MemoryToTape() last block done = %d\n",
                    last_block_done));
Olof Barring's avatar
Olof Barring committed
624
625
626
627
628
            /*
             * Reset all switches so that the buffer can be reused
             */
            databufs[i]->bufendp = 0;
            databufs[i]->data_length = 0;
629
            databufs[i]->nbrecs = 0;
Olof Barring's avatar
Olof Barring committed
630
631
632
633
634
635
636
637
638
639
640
641
642
643
            databufs[i]->end_of_tpfile = FALSE;
            databufs[i]->last_buffer = FALSE;
            databufs[i]->flag = BUFFER_EMPTY;
            buf_done = TRUE;
            /*
             * Increment the circular data buffer index and reset the
             * tape block index.
             */
            *indxp = (*indxp+1) % nb_bufs;
            *firstblk = 0;
        }
        /*
         * Release lock on this buffer
         */
644
        if ( databufs[i]->nb_waiters > 0 && NoSyncAccess == 0 ) {
645
646
647
648
            rc = Cthread_cond_broadcast_ext(databufs[i]->lock);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() Cthread_cond_broadcast_ext(): %s\n",
                    sstrerror(serrno));
649
650
651
652
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "Cthread_cond_broadcast_ext",
                                 "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
653
654
655
656
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
657
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
658
                return(-1);
659
            }
Olof Barring's avatar
Olof Barring committed
660
        }
661
662
663
664
665
        if ( NoSyncAccess == 0 ) {
            rc = Cthread_mutex_unlock_ext(databufs[i]->lock);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() Cthread_mutex_unlock_ext(): %s\n",
                    sstrerror(serrno));
666
667
668
669
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "Cthread_mutex_unlock_ext",
                                 "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
670
671
672
673
674
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
                return(-1);
675
            }
Olof Barring's avatar
Olof Barring committed
676
677
        }

678
        if ( buf_done == TRUE && NoSyncAccess == 0 ) {
679
            (void)rtcpd_nbFullBufs(-1);
Olof Barring's avatar
Olof Barring committed
680
681
682
683
684
685
686
            /*
             * Decrement the number of reserved buffers.
             */
            rc = Cthread_mutex_lock_ext(proc_cntl.cntl_lock);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() Cthread_mutex_lock_ext(): %s\n",
                    sstrerror(serrno));
687
688
689
690
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "Cthread_mutex_lock_ext",
                                 "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
691
692
693
694
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
Olof Barring's avatar
Olof Barring committed
695
696
697
                return(-1);
            }
            proc_cntl.nb_reserved_bufs--;
698
699
            /*
             * Check if disk IO has finished. If so, we don't need to sync.
700
701
702
703
704
             * buffers anymore. The test on diskIOstarted may seem a bit
             * unlogical but in fact this flag should have been set by the
             * thread started before we can allow no sync. access - there
             * is a window where disk IO starter can exit before the last
             * disk IO thread has started. 
705
706
             */
            if ( proc_cntl.diskIOfinished == 1 && 
707
                 proc_cntl.diskIOstarted == 1 &&
708
709
                 proc_cntl.nb_diskIOactive == 0 ) {
                rtcp_log(LOG_DEBUG,"MemoryToTape() disk IO has finished! Sync. not needed anymore\n");
710
711
712
                tl_rtcpd.tl_log( &tl_rtcpd, 10, 2, 
                                 "func"   , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message", TL_MSG_PARAM_STR, "disk IO has finished! Sync. not needed anymore" );
713
714
                NoSyncAccess = *diskIOfinished = 1;
            }
Olof Barring's avatar
Olof Barring committed
715
716
717
718

            /*
             * Signal to main thread that we changed cntl info
             */
719
720
721
722
723
            if ( proc_cntl.nb_reserved_bufs < nb_bufs ) {
                rc = Cthread_cond_broadcast_ext(proc_cntl.cntl_lock);
                if ( rc == -1 ) {
                    rtcp_log(LOG_ERR,"MemoryToTape() Cthread_cond_broadcast_ext(proc_cntl): %s\n",
                        sstrerror(serrno));
724
725
726
727
                    tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                     "func"    , TL_MSG_PARAM_STR, "MemoryToTape",
                                     "Message" , TL_MSG_PARAM_STR, "Cthread_cond_broadcast_ext(proc_cntl)",
                                     "Error"   , TL_MSG_PARAM_STR, sstrerror(serrno));
728
729
730
731
                    if ( (convert & FIXVAR) != 0 ) {
                        if ( convert_buffer != NULL ) free(convert_buffer);
                        if ( convert_context != NULL ) free(convert_context);
                    }
732
                    (void)Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
733
                    return(-1);
734
                }
Olof Barring's avatar
Olof Barring committed
735
736
737
738
739
740
            }

            rc = Cthread_mutex_unlock_ext(proc_cntl.cntl_lock);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"MemoryToTape() Cthread_mutex_unlock_ext(): %s\n",
                    sstrerror(serrno));
741
742
743
744
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"    , TL_MSG_PARAM_STR, "MemoryToTape",
                                 "Message" , TL_MSG_PARAM_STR, "Cthread_mutex_unlock_ext",
                                 "Error"   , TL_MSG_PARAM_STR, sstrerror(serrno));
745
746
747
748
                if ( (convert & FIXVAR) != 0 ) {
                    if ( convert_buffer != NULL ) free(convert_buffer);
                    if ( convert_context != NULL ) free(convert_context);
                }
Olof Barring's avatar
Olof Barring committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
                return(-1);
            }
        }

        /*
         * Break out to main tape IO loop if we have hit 
         * the end of the current tape file
         */
        if ( end_of_tpfile == TRUE ) break;
        /*
         * Check if we reached end of volume. If so, return to
         * let the main tapeIO loop iterate one step in the tape
         * request list. This must be the last file request (in
         * a multi-volume request only the last file can span). Note
         * that we have to start on the same indxp since the last
         * buffer has not been completely written out.
         */
        if ( file->eovflag == 1 ) break;
        /*
         * Check if last block
         */
        if ( last_block_done != 0 ) break;
        /*
         * Has something fatal happened while we were occupied
         * writing to the tape?
         */
775
        rtcpd_CheckReqStatus(NULL,file,NULL,&severity);
776
        if ( (proc_err = ((severity | rtcpd_CheckProcError()) & 
777
              RTCP_FAILED)) != 0 ) {
778
            break;
779
        }
Olof Barring's avatar
Olof Barring committed
780
781
    } /* End of for (;;) */

782
783
784
785
    if ( ((convert & FIXVAR) != 0) && (convert_buffer != NULL) ) {
        /*
         * Write out spill from VarToFix conversion
         */
786
787
        rtcp_log(LOG_DEBUG,"MemoryToTape() FIXVAR spill: %d, proc_err=%d\n",
                 spill,proc_err);
788
789
790
791
792
        tl_rtcpd.tl_log( &tl_rtcpd, 11, 4, 
                         "func"    , TL_MSG_PARAM_STR, "MemoryToTape",
                         "Message" , TL_MSG_PARAM_STR, "FIXVAR",
                         "spill"   , TL_MSG_PARAM_INT, spill,
                         "proc_err", TL_MSG_PARAM_INT, proc_err );
793
        if ( proc_err == 0  && spill > 0 ) {
794
            if ( (convert & EBCCONV) != 0 ) asc2ebc(convert_buffer,spill);
795
796
797
798
            rc = twrite(tape_fd,
                        convert_buffer,
                        spill,
                        tape,
799
800
                        file,
                        tapeFlushMode);
801
            TP_SIZE(rc);
802
803
804
805
806
807
808
809
810
        }
        if ( nb_truncated > 0 ) {
            rtcpd_AppendClientMsg(NULL,file,RT222,"CPDSKTP",
                nb_truncated);
        }
        free(convert_buffer);
        if ( convert_context != NULL ) free(convert_context);
    }

811
    TP_STATUS(RTCP_PS_CLOSE);
812
813
814
815
816
817
818
    if ( proc_err == 0 ) rc = tclose(tape_fd,tape,file,tapeFlushMode,
        nbBytesWrittenWithoutFlush,
        nbFilesWrittenWithoutFlush,
        maxBytesBeforeFlush,
        maxFilesBeforeFlush,
        flushedToTapeAfterNFiles,
        batchBytesToTape);
Olof Barring's avatar
Olof Barring committed
819
    TP_STATUS(RTCP_PS_NOBLOCKING);
820

Olof Barring's avatar
Olof Barring committed
821
822
823
824
825
826
827
    return(rc);
}

static int TapeToMemory(int tape_fd, int *indxp, int *firstblk,
                        tape_list_t *tape, 
                        file_list_t *file) {
    int nb_bytes, rc, i, j, last_sz, blksiz, current_bufsz;
828
    int lrecl, end_of_tpfile, break_and_return, severity, proc_err;
Olof Barring's avatar
Olof Barring committed
829
    int nb_skipped_blks = 0;
830
831
    register int Uformat;
    register int debug = Debug;
Olof Barring's avatar
Olof Barring committed
832
    rtcpFileRequest_t *filereq = NULL;
833
    extern char *u64tostr (u_signed64, char *, int);
Olof Barring's avatar
Olof Barring committed
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853

    if ( tape_fd < 0 || indxp == NULL || firstblk == NULL ||
         tape == NULL || file == NULL ) {
        serrno = EINVAL;
        return(-1);
    }
    filereq = &file->filereq;

    /*
     * In the case when startsize > maxsize, i.e. we are concatenating
     * tape files to a single disk file and the max size has been
     * exceeded, we still need to enter the loop in order to flag a
     * buffer full to wake up the disk IO thread. However no data
     * will be read from tape since tapebytes_sofar exceeds maxsize
     * already from the beginning. See notice further down (immediately
     * before the tread()).
     */
    file->tapebytes_sofar = filereq->startsize;
    blksiz = filereq->blocksize;
    lrecl = filereq->recordlength;
854
    Uformat = (*filereq->recfm == 'U' ? TRUE : FALSE);
855
    if ( Uformat == TRUE ) lrecl = 0;
Olof Barring's avatar
Olof Barring committed
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874

    /*
     * Calculate new actual buffer length
     */
    current_bufsz = rtcpd_CalcBufSz(tape,file);
    if ( current_bufsz == -1 ) return(-1);
    /*
     * Tape read loop to break out of. We must assure that there
     * are at least one empty buffer available for next disk IO
     * thread before signaling end of tape file to main control
     * thread. The reason for this is to avoid conflicting access
     * between two disk IO thread on the same buffer in case the
     * network or remote disk is much slower than the tape IO. Thus
     * we must assure that the buffer following the last tape file
     * buffer is empty which means that the currently active disk IO
     * thread has finished with it.
     */
    end_of_tpfile = FALSE;
    break_and_return = FALSE;
875
    proc_err = 0;
Olof Barring's avatar
Olof Barring committed
876
877
878
879
880
881
882
883
884
885
886
    for (;;) {
        i = *indxp;
        /*
         * Synchronize access to next buffer
         */
        TP_STATUS(RTCP_PS_WAITMTX);
        rc = Cthread_mutex_lock_ext(databufs[i]->lock);
        TP_STATUS(RTCP_PS_NOBLOCKING);
        if ( rc == -1 ) {
            rtcp_log(LOG_ERR,"TapeToMemory() Cthread_mutex_lock_ext(): %s\n",
                sstrerror(serrno));
887
888
889
890
            tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                             "func"   , TL_MSG_PARAM_STR, "TapeToMemory",
                             "Message", TL_MSG_PARAM_STR, "Cthread_mutex_lock_ext",
                             "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
Olof Barring's avatar
Olof Barring committed
891
892
893
894
895
896
            return(-1);
        }
        /*
         * Wait until it is empty.
         */
        while (databufs[i]->flag == BUFFER_FULL) {
897
898
            rtcpd_CheckReqStatus(NULL,file,NULL,&severity);
            if ( (proc_err = ((severity | rtcpd_CheckProcError()) & 
899
                  RTCP_FAILED)) != 0 ) {
900
901
902
903
904
                (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
                break;
            }

905
906
            DEBUG_PRINT((LOG_DEBUG,"TapeToMemory() wait on buffer[%d]->flag=%d\n",
                i,databufs[i]->flag));
907
            databufs[i]->nb_waiters++;
Olof Barring's avatar
Olof Barring committed
908
909
910
911
912
913
            TP_STATUS(RTCP_PS_WAITCOND);
            rc = Cthread_cond_wait_ext(databufs[i]->lock);
            TP_STATUS(RTCP_PS_NOBLOCKING);
            if ( rc == -1 ) {
                rtcp_log(LOG_ERR,"TapeToMemory() Cthread_cond_wait_ext(): %s\n",
                    sstrerror(serrno));
914
915
916
917
                tl_rtcpd.tl_log( &tl_rtcpd, 3, 3, 
                                 "func"   , TL_MSG_PARAM_STR, "TapeToMemory",
                                 "Message", TL_MSG_PARAM_STR, "Cthread_cond_wait_ext",
                                 "Error"  , TL_MSG_PARAM_STR, sstrerror(serrno));
918
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
Olof Barring's avatar
Olof Barring committed
919
920
                return(-1);
            }
921
            databufs[i]->nb_waiters--;
922
923
924
        } /* while (databufs[i]->flag == BUFFER_FULL) */

        if ( databufs[i]->flag == BUFFER_EMPTY ) {
925
            rtcpd_CheckReqStatus(NULL,file,NULL,&severity);
926
            if ( (proc_err = ((severity | rtcpd_CheckProcError()) & 
927
                  RTCP_FAILED)) != 0 ) {
Olof Barring's avatar
Olof Barring committed
928
929
930
                (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                (void)Cthread_mutex_unlock_ext(databufs[i]->lock);
            }
931
        }
932
        if ( proc_err != 0 ) break;
933
        DEBUG_PRINT((LOG_DEBUG,"TapeToMemory() buffer %d empty\n",i));
Olof Barring's avatar
Olof Barring committed
934
935
936
937
938
939
940
941
942
943
944
945
946
947
        if ( end_of_tpfile == FALSE ) {
            /*
             * Set the actual buffer size to match current block size
             */
            databufs[i]->length = current_bufsz;
            /*
             * Reset switches (may remain old settings from a previous file).
             */
            databufs[i]->end_of_tpfile = FALSE;
            databufs[i]->last_buffer = FALSE;
            /*
             * Copy the data from tape
             */
            last_sz = 0;
948
949
950
951
952
953
            databufs[i]->nbrecs = 0;
            /*
             * If U-format, re-allocate the lrecl_table[] if needed.
             */
            if ( Uformat == TRUE ) rc = rtcpd_AdmUformatInfo(file,i);

954
            for (j=*firstblk; last_sz+blksiz < databufs[i]->length; j++) {
Olof Barring's avatar
Olof Barring committed
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
                /*
                 * Max size may have been exceeded even before we
                 * read any data at all. This happens when we are 
                 * concatenating on disk and max size is already 
                 * exceeded already at entry (i.e. startsize > maxsize).
                 * We still need to flag the buffer full to wake up
                 * the disk IO thread.
                 * Note that in the normal case (where we already have 
                 * read some data) the max size limit is tested after 
                 * the read. In that case the following test is always
                 * false.
                 */
                if ( (filereq->maxsize > 0) && 
                     (file->tapebytes_sofar >= filereq->maxsize) ) {
                    /*
                     * Nothing will be copied!
                     */
                    filereq->bytes_out = 0;
                    end_of_tpfile = TRUE;
974
                    break;
Olof Barring's avatar
Olof Barring committed
975
976
977
978
979
980
981
982
983
984
985
986
987
                }

                /*
                 * Read a block
                 */
                end_of_tpfile = FALSE;
                nb_bytes = blksiz;

                /*
                 * >>>>>>>>>>> read from tape <<<<<<<<<<<<<
                 */
                TP_STATUS(RTCP_PS_READ);
                rc = tread(tape_fd,
988
                           databufs[i]->buffer + last_sz,
Olof Barring's avatar
Olof Barring committed
989
990
991
                           nb_bytes,
                           tape,
                           file);
Benjamin Couturier's avatar
Benjamin Couturier committed
992

Olof Barring's avatar
Olof Barring committed
993
                TP_STATUS(RTCP_PS_NOBLOCKING);
994
995
                if ( rc == -1 ) {
                    rtcp_log(LOG_ERR,"TapeToMemory() tape read error\n");
996
997
998
                    tl_rtcpd.tl_log( &tl_rtcpd, 3, 2, 
                                     "func"   , TL_MSG_PARAM_STR, "TapeToMemory",
                                     "Message", TL_MSG_PARAM_STR, "tape read error" );
Olof Barring's avatar
Olof Barring committed
999
1000
                    (void)Cthread_cond_broadcast_ext(databufs[i]->lock);
                    (void)Cthread_mutex_unlock_ext(databufs[i]->lock);