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,14 +500,15 @@ QString getAbsolutePath(const QString &filename)
500 return QFileInfo(filename).absoluteFilePath(); 500 return QFileInfo(filename).absoluteFilePath();
501 } 501 }
502 502
  503 +const int base_block = 100000000;
  504 +
503 BlockCompression::BlockCompression(QIODevice *_basis) 505 BlockCompression::BlockCompression(QIODevice *_basis)
504 { 506 {
505 - blockSize = 100000000; 507 + blockSize = base_block;
506 setBasis(_basis); 508 setBasis(_basis);
507 } 509 }
508 510
509 -BlockCompression::BlockCompression() { blockSize = 100000000; };  
510 - 511 +BlockCompression::BlockCompression() { blockSize = base_block;};
511 512
512 bool BlockCompression::open(QIODevice::OpenMode mode) 513 bool BlockCompression::open(QIODevice::OpenMode mode)
513 { 514 {
@@ -521,14 +522,22 @@ bool BlockCompression::open(QIODevice::OpenMode mode) @@ -521,14 +522,22 @@ bool BlockCompression::open(QIODevice::OpenMode mode)
521 blockWriter.setDevice(basis); 522 blockWriter.setDevice(basis);
522 523
523 if (mode & QIODevice::WriteOnly) { 524 if (mode & QIODevice::WriteOnly) {
524 - precompressedBlockWriter = new QBuffer;  
525 - precompressedBlockWriter->open(QIODevice::ReadWrite); 525 + precompressedBlockWriter.open(QIODevice::WriteOnly);
526 } 526 }
527 else if (mode & QIODevice::ReadOnly) { 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 QByteArray compressedBlock; 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 decompressedBlock = qUncompress(compressedBlock); 539 decompressedBlock = qUncompress(compressedBlock);
  540 +
532 decompressedBlockReader.setBuffer(&decompressedBlock); 541 decompressedBlockReader.setBuffer(&decompressedBlock);
533 decompressedBlockReader.open(QIODevice::ReadOnly); 542 decompressedBlockReader.open(QIODevice::ReadOnly);
534 } 543 }
@@ -538,11 +547,17 @@ bool BlockCompression::open(QIODevice::OpenMode mode) @@ -538,11 +547,17 @@ bool BlockCompression::open(QIODevice::OpenMode mode)
538 547
539 void BlockCompression::close() 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 basis->close(); 561 basis->close();
547 } 562 }
548 563
@@ -557,8 +572,10 @@ void BlockCompression::setBasis(QIODevice *_basis) @@ -557,8 +572,10 @@ void BlockCompression::setBasis(QIODevice *_basis)
557 // block from basis 572 // block from basis
558 qint64 BlockCompression::readData(char *data, qint64 remaining) 573 qint64 BlockCompression::readData(char *data, qint64 remaining)
559 { 574 {
  575 + qint64 initial = remaining;
560 qint64 read = 0; 576 qint64 read = 0;
561 while (remaining > 0) { 577 while (remaining > 0) {
  578 + // attempt to read the target amount of data
562 qint64 single_read = decompressedBlockReader.read(data, remaining); 579 qint64 single_read = decompressedBlockReader.read(data, remaining);
563 if (single_read == -1) 580 if (single_read == -1)
564 qFatal("miss read"); 581 qFatal("miss read");
@@ -567,13 +584,21 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) @@ -567,13 +584,21 @@ qint64 BlockCompression::readData(char *data, qint64 remaining)
567 read += single_read; 584 read += single_read;
568 data += single_read; 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 if (remaining > 0) { 588 if (remaining > 0) {
572 QByteArray compressedBlock; 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 decompressedBlock = qUncompress(compressedBlock); 602 decompressedBlock = qUncompress(compressedBlock);
578 603
579 decompressedBlockReader.close(); 604 decompressedBlockReader.close();
@@ -581,7 +606,12 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) @@ -581,7 +606,12 @@ qint64 BlockCompression::readData(char *data, qint64 remaining)
581 decompressedBlockReader.open(QIODevice::ReadOnly); 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 bool BlockCompression::isSequential() const 617 bool BlockCompression::isSequential() const
@@ -591,36 +621,57 @@ bool BlockCompression::isSequential() const @@ -591,36 +621,57 @@ bool BlockCompression::isSequential() const
591 621
592 qint64 BlockCompression::writeData(const char *data, qint64 remaining) 622 qint64 BlockCompression::writeData(const char *data, qint64 remaining)
593 { 623 {
  624 + const char * endPoint = data + remaining;
  625 + qint64 initial = remaining;
  626 +
594 qint64 written = 0; 627 qint64 written = 0;
595 628
596 while (remaining > 0) { 629 while (remaining > 0) {
597 // how much more can be put in this buffer? 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 // don't try to write beyond capacity 635 // don't try to write beyond capacity
601 qint64 write_size = qMin(capacity, remaining); 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 if (singleWrite == -1) 640 if (singleWrite == -1)
607 - singleWrite = 0; 641 + qFatal("matrix write failure?");
608 642
609 remaining -= singleWrite; 643 remaining -= singleWrite;
610 data += singleWrite; 644 data += singleWrite;
611 written += singleWrite; 645 written += singleWrite;
  646 + if (data > endPoint)
  647 + qFatal("Wrote past the end");
612 648
613 if (remaining > 0) { 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 return basis->isWritable() ? written : -1; 675 return basis->isWritable() ? written : -1;
625 } 676 }
626 677
openbr/core/qtutils.h
@@ -122,7 +122,7 @@ namespace QtUtils @@ -122,7 +122,7 @@ namespace QtUtils
122 122
123 // write to a QByteArray, when max block sized is reached, compress and write 123 // write to a QByteArray, when max block sized is reached, compress and write
124 // it to basis 124 // it to basis
125 - QBuffer * precompressedBlockWriter; 125 + QBuffer precompressedBlockWriter;
126 QDataStream blockWriter; 126 QDataStream blockWriter;
127 qint64 writeData(const char *data, qint64 remaining); 127 qint64 writeData(const char *data, qint64 remaining);
128 }; 128 };