Commit b54d2f75d611f67ef449fc6ce292e01e96ca08a0

Authored by caotto
2 parents cffc1b76 f81cb10d

Merge pull request #334 from biometrics/bytearray_serialization

Explicit bytearray serialization
openbr/core/qtutils.cpp
... ... @@ -500,14 +500,15 @@ QString getAbsolutePath(const QString &filename)
500 500 return QFileInfo(filename).absoluteFilePath();
501 501 }
502 502  
  503 +const int base_block = 100000000;
  504 +
503 505 BlockCompression::BlockCompression(QIODevice *_basis)
504 506 {
505   - blockSize = 100000000;
  507 + blockSize = base_block;
506 508 setBasis(_basis);
507 509 }
508 510  
509   -BlockCompression::BlockCompression() { blockSize = 100000000; };
510   -
  511 +BlockCompression::BlockCompression() { blockSize = base_block;};
511 512  
512 513 bool BlockCompression::open(QIODevice::OpenMode mode)
513 514 {
... ... @@ -521,14 +522,22 @@ bool BlockCompression::open(QIODevice::OpenMode mode)
521 522 blockWriter.setDevice(basis);
522 523  
523 524 if (mode & QIODevice::WriteOnly) {
524   - precompressedBlockWriter = new QBuffer;
525   - precompressedBlockWriter->open(QIODevice::ReadWrite);
  525 + precompressedBlockWriter.open(QIODevice::WriteOnly);
526 526 }
527 527 else if (mode & QIODevice::ReadOnly) {
  528 +
  529 + // Read an initial compressed block from the underlying QIODevice,
  530 + // decompress, and set up a reader on it
528 531 QByteArray compressedBlock;
529   - blockReader >> compressedBlock;
  532 + quint32 block_size;
  533 + blockReader >> block_size;
  534 + compressedBlock.resize(block_size);
  535 + int read_count = blockReader.readRawData(compressedBlock.data(), block_size);
  536 + if (read_count != block_size)
  537 + qFatal("Failed to read initial block");
530 538  
531 539 decompressedBlock = qUncompress(compressedBlock);
  540 +
532 541 decompressedBlockReader.setBuffer(&decompressedBlock);
533 542 decompressedBlockReader.open(QIODevice::ReadOnly);
534 543 }
... ... @@ -538,11 +547,17 @@ bool BlockCompression::open(QIODevice::OpenMode mode)
538 547  
539 548 void BlockCompression::close()
540 549 {
541   - // flush output buffer
542   - if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter) {
543   - QByteArray compressedBlock = qCompress(precompressedBlockWriter->buffer(), -1);
544   - blockWriter << compressedBlock;
  550 + // flush output buffer, since we may have a partial block which hasn't been
  551 + // written to disk yet.
  552 + if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter.isOpen()) {
  553 + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer());
  554 + precompressedBlockWriter.close();
  555 +
  556 + quint32 bsize= compressedBlock.size();
  557 + blockWriter << bsize;
  558 + blockWriter.writeRawData(compressedBlock.data(), compressedBlock.size());
545 559 }
  560 + // close the underlying device.
546 561 basis->close();
547 562 }
548 563  
... ... @@ -557,8 +572,10 @@ void BlockCompression::setBasis(QIODevice *_basis)
557 572 // block from basis
558 573 qint64 BlockCompression::readData(char *data, qint64 remaining)
559 574 {
  575 + qint64 initial = remaining;
560 576 qint64 read = 0;
561 577 while (remaining > 0) {
  578 + // attempt to read the target amount of data
562 579 qint64 single_read = decompressedBlockReader.read(data, remaining);
563 580 if (single_read == -1)
564 581 qFatal("miss read");
... ... @@ -567,13 +584,21 @@ qint64 BlockCompression::readData(char *data, qint64 remaining)
567 584 read += single_read;
568 585 data += single_read;
569 586  
570   - // need a new block
  587 + // need a new block if we didn't get enough bytes from the previous read
571 588 if (remaining > 0) {
572 589 QByteArray compressedBlock;
573   - blockReader >> compressedBlock;
574   - if (compressedBlock.size() == 0) {
575   - return read;
576   - }
  590 +
  591 + // read the size of the next block
  592 + quint32 block_size;
  593 + blockReader >> block_size;
  594 + if (block_size == 0)
  595 + break;
  596 +
  597 + compressedBlock.resize(block_size);
  598 + int actualRead = blockReader.readRawData(compressedBlock.data(), block_size);
  599 + if (actualRead != block_size)
  600 + qFatal("Bad read on nominal block size: %d, only got %d", block_size, remaining);
  601 +
577 602 decompressedBlock = qUncompress(compressedBlock);
578 603  
579 604 decompressedBlockReader.close();
... ... @@ -581,7 +606,12 @@ qint64 BlockCompression::readData(char *data, qint64 remaining)
581 606 decompressedBlockReader.open(QIODevice::ReadOnly);
582 607 }
583 608 }
584   - return blockReader.atEnd() && !basis->isReadable() ? -1 : read;
  609 +
  610 + bool condition = blockReader.atEnd() && !basis->isReadable() ;
  611 + if (condition)
  612 + qWarning("Returning -1 from read");
  613 +
  614 + return condition ? -1 : read;
585 615 }
586 616  
587 617 bool BlockCompression::isSequential() const
... ... @@ -591,36 +621,57 @@ bool BlockCompression::isSequential() const
591 621  
592 622 qint64 BlockCompression::writeData(const char *data, qint64 remaining)
593 623 {
  624 + const char * endPoint = data + remaining;
  625 + qint64 initial = remaining;
  626 +
594 627 qint64 written = 0;
595 628  
596 629 while (remaining > 0) {
597 630 // how much more can be put in this buffer?
598   - qint64 capacity = blockSize - precompressedBlockWriter->pos();
  631 + qint64 capacity = blockSize - precompressedBlockWriter.pos();
  632 + if (capacity < 0)
  633 + qFatal("Negative capacity!!!");
599 634  
600 635 // don't try to write beyond capacity
601 636 qint64 write_size = qMin(capacity, remaining);
602 637  
603   - qint64 singleWrite = precompressedBlockWriter->write(data, write_size);
604   - // ignore the error case here, we consdier basis's failure mode the real
605   - // end case
  638 + qint64 singleWrite = precompressedBlockWriter.write(data, write_size);
  639 +
606 640 if (singleWrite == -1)
607   - singleWrite = 0;
  641 + qFatal("matrix write failure?");
608 642  
609 643 remaining -= singleWrite;
610 644 data += singleWrite;
611 645 written += singleWrite;
  646 + if (data > endPoint)
  647 + qFatal("Wrote past the end");
612 648  
613 649 if (remaining > 0) {
614   - QByteArray compressedBlock = qCompress(precompressedBlockWriter->buffer(), -1);
  650 + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer(), -1);
615 651  
616   - if (compressedBlock.size() != 0)
617   - blockWriter << compressedBlock;
  652 + if (precompressedBlockWriter.buffer().size() != 0) {
  653 + quint32 block_size = compressedBlock.size();
  654 + blockWriter << block_size;
618 655  
619   - delete precompressedBlockWriter;
620   - precompressedBlockWriter = new QBuffer;
621   - precompressedBlockWriter->open(QIODevice::ReadWrite);
  656 + int write_count = blockWriter.writeRawData(compressedBlock.data(), block_size);
  657 + if (write_count != block_size)
  658 + qFatal("Didn't write enough data");
  659 + }
  660 + else
  661 + qFatal("serialized empty compressed block (?)");
  662 +
  663 + precompressedBlockWriter.close();
  664 + precompressedBlockWriter.open(QIODevice::WriteOnly);
622 665 }
623 666 }
  667 +
  668 + if (written != initial)
  669 + qFatal("didn't write enough bytes");
  670 +
  671 + bool condition = basis->isWritable();
  672 + if (!condition)
  673 + qWarning("Returning -1 from write");
  674 +
624 675 return basis->isWritable() ? written : -1;
625 676 }
626 677  
... ...
openbr/core/qtutils.h
... ... @@ -122,7 +122,7 @@ namespace QtUtils
122 122  
123 123 // write to a QByteArray, when max block sized is reached, compress and write
124 124 // it to basis
125   - QBuffer * precompressedBlockWriter;
  125 + QBuffer precompressedBlockWriter;
126 126 QDataStream blockWriter;
127 127 qint64 writeData(const char *data, qint64 remaining);
128 128 };
... ...