Вставьте изображение в BLOB в Sqlite - PullRequest
0 голосов
/ 13 апреля 2020

Я читаю каталог для 600 000 изображений и хочу сохранить эти изображения в Sqlite DB. Структура БД - это просто ID, IMAGE (blob).

Я не разбираюсь в C ++, поэтому выясняю это.

Сначала я открываю файл DB и настраиваю оператор prepare et c

int rc = sqlite3_open_v2(filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);

char* errorMessage;
sqlite3_exec(db, "PRAGMA synchronous=OFF", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA count_changes=OFF", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA journal_mode=MEMORY", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA cache_size=1", NULL, NULL, &errorMessage);

sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &errorMessage);

char const *szSQL = "INSERT INTO images (image) VALUES (?);";
int rc = sqlite3_prepare_v2(db, szSQL, -1, &stmt, NULL);
if( rc != SQLITE_OK ) {
  printf("PREPARE FAILED. EXITING\n");
  exit(0);
}

Затем некоторое время l oop перебирает все файлы в каталоге. Чтобы прочитать изображение в символ * (для большого двоичного объекта), я использую следующий код:

char text[10] = {'\0'};
struct stat s;
int status = stat(fullimagepath.c_str(), &s);
int fd = open(fullimagepath.c_str(), O_RDONLY);
if (fd == -1)
{
    perror("Error opening file for reading");
    exit(1);
}

char *fileContent = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);

Приведенный ниже код запускается также на каждой итерации, где он связывает большой двоичный объект и пытается вставить

int retVal = sqlite3_bind_blob(stmt, 1, fileContent, s.st_size, NULL);
if (retVal != SQLITE_OK) {
  fprintf(stderr, "ERROR %s %s\n", fullimagepath.c_str(), sqlite3_errmsg(db));
  sqlite3_finalize(stmt);
  sqlite3_close(db);
  exit(1);
}

retVal = sqlite3_step(stmt);
if (retVal != SQLITE_DONE && retVal != SQLITE_ROW) {
      sqlite3_finalize(stmt);
      sqlite3_close(db);
      fprintf(stderr, "ERROR %d\n", retVal);
      exit(1);
}
fprintf(stderr, "1f2 %s\n", fullimagepath.c_str());


sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);

Где fullimagepath - это полный путь к изображению каждый раз (описанное выше через некоторое время l oop перебирает файлы в каталоге).

После того, как полный каталог сделан, мы запустите коммит и закройте БД.

sqlite3_exec(db, "COMMIT", NULL, NULL, &errorMessage);
sqlite3_finalize(stmt);
sqlite3_close(db);

Проблема, с которой я столкнулся, заключается в том, что после запуска ряда файлов она останавливается с segmentation fault.

Насколько я может через различные испытания определить, где я поменял большой двоичный объект на текстовый и другие, это происходит только при попытке вставить большой двоичный объект.

Может ли кто-нибудь указать мне правильное направление, чтобы исправить это, пожалуйста?

При работе в меньшем каталоге с менее чем 10000 изображений он работает нормально. Или, если вам нужна дополнительная информация, пожалуйста, сообщите.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 14 апреля 2020

Я наконец-то разобрался с проблемой после @Surt в самом первом комментарии, где упоминалось "где ты мунмап". Я не знал, что это значит, и после долгих поисков в других местах заметил комментарий, упоминающий об этом. Немного больше поиграл и понял, что это довольно важно. Разместил следующее

status = munmap(fileContent, s.st_size);
sqlite3_reset(stmt);

Спасибо тем, кто прокомментировал указатели в правильном направлении. Очень ценится.

0 голосов
/ 13 апреля 2020

Я подозреваю, что вы используете нашу память, поэтому проверьте ее.

char *fileContent = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED | MAP_POPULATE , fd, 0);
if (!fileContent) {
    perror("Error mapping file");
    exit(1);
}
close(fd);
...