~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/csv/ha_tina.cc

  • Committer: Brian Aker
  • Date: 2009-11-24 02:06:37 UTC
  • mfrom: (1223.1.7 push)
  • Revision ID: brian@gaz-20091124020637-9gb65vj98x1arydm
MergeĀ forĀ staging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
424
424
  return(0);
425
425
}
426
426
 
427
 
bool ha_tina::check_and_repair(Session *session)
428
 
{
429
 
  HA_CHECK_OPT check_opt;
430
 
 
431
 
  check_opt.init();
432
 
 
433
 
  return(repair(session, &check_opt));
434
 
}
435
 
 
436
 
 
437
427
int ha_tina::init_tina_writer()
438
428
{
439
429
  /*
455
445
}
456
446
 
457
447
 
458
 
bool ha_tina::is_crashed() const
459
 
{
460
 
  return(share->crashed);
461
 
}
462
 
 
463
448
/*
464
449
  Free lock controls.
465
450
*/
1078
1063
  All table scans call this first.
1079
1064
  The order of a table scan is:
1080
1065
 
1081
 
  ha_tina::store_lock
1082
1066
  ha_tina::info
1083
1067
  ha_tina::rnd_init
1084
1068
  ha_tina::extra
1347
1331
 
1348
1332
 
1349
1333
/*
1350
 
  Repair CSV table in the case, it is crashed.
1351
 
 
1352
 
  SYNOPSIS
1353
 
    repair()
1354
 
    session         The thread, performing repair
1355
 
    check_opt   The options for repair. We do not use it currently.
1356
 
 
1357
 
  DESCRIPTION
1358
 
    If the file is empty, change # of rows in the file and complete recovery.
1359
 
    Otherwise, scan the table looking for bad rows. If none were found,
1360
 
    we mark file as a good one and return. If a bad row was encountered,
1361
 
    we truncate the datafile up to the last good row.
1362
 
 
1363
 
   TODO: Make repair more clever - it should try to recover subsequent
1364
 
         rows (after the first bad one) as well.
1365
 
*/
1366
 
 
1367
 
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1368
 
{
1369
 
  char repaired_fname[FN_REFLEN];
1370
 
  unsigned char *buf;
1371
 
  File repair_file;
1372
 
  int rc;
1373
 
  ha_rows rows_repaired= 0;
1374
 
  off_t write_begin= 0, write_end;
1375
 
 
1376
 
  /* empty file */
1377
 
  if (!share->saved_data_file_length)
1378
 
  {
1379
 
    share->rows_recorded= 0;
1380
 
    goto end;
1381
 
  }
1382
 
 
1383
 
  /* Don't assert in field::val() functions */
1384
 
  table->use_all_columns();
1385
 
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1386
 
    return(HA_ERR_OUT_OF_MEM);
1387
 
 
1388
 
  /* position buffer to the start of the file */
1389
 
  if (init_data_file())
1390
 
    return(HA_ERR_CRASHED_ON_REPAIR);
1391
 
 
1392
 
  /*
1393
 
    Local_saved_data_file_length is initialized during the lock phase.
1394
 
    Sometimes this is not getting executed before ::repair (e.g. for
1395
 
    the log tables). We set it manually here.
1396
 
  */
1397
 
  local_saved_data_file_length= share->saved_data_file_length;
1398
 
  /* set current position to the beginning of the file */
1399
 
  current_position= next_position= 0;
1400
 
 
1401
 
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
1402
 
 
1403
 
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1404
 
  while (!(rc= find_current_row(buf)))
1405
 
  {
1406
 
    session_inc_row_count(session);
1407
 
    rows_repaired++;
1408
 
    current_position= next_position;
1409
 
  }
1410
 
 
1411
 
  free_root(&blobroot, MYF(0));
1412
 
 
1413
 
  free((char*)buf);
1414
 
 
1415
 
  if (rc == HA_ERR_END_OF_FILE)
1416
 
  {
1417
 
    /*
1418
 
      All rows were read ok until end of file, the file does not need repair.
1419
 
      If rows_recorded != rows_repaired, we should update rows_recorded value
1420
 
      to the current amount of rows.
1421
 
    */
1422
 
    share->rows_recorded= rows_repaired;
1423
 
    goto end;
1424
 
  }
1425
 
 
1426
 
  /*
1427
 
    Otherwise we've encountered a bad row => repair is needed.
1428
 
    Let us create a temporary file.
1429
 
  */
1430
 
  if ((repair_file= my_create(fn_format(repaired_fname, share->table_name,
1431
 
                                        "", CSN_EXT,
1432
 
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1433
 
                           0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1434
 
    return(HA_ERR_CRASHED_ON_REPAIR);
1435
 
 
1436
 
  file_buff->init_buff(data_file);
1437
 
 
1438
 
 
1439
 
  /* we just truncated the file up to the first bad row. update rows count. */
1440
 
  share->rows_recorded= rows_repaired;
1441
 
 
1442
 
  /* write repaired file */
1443
 
  while (1)
1444
 
  {
1445
 
    write_end= std::min(file_buff->end(), current_position);
1446
 
 
1447
 
    off_t write_length= write_end - write_begin;
1448
 
    if ((uint64_t)write_length > SIZE_MAX)
1449
 
    {
1450
 
      return -1;
1451
 
    }
1452
 
    if ((write_length) &&
1453
 
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
1454
 
                  (size_t)write_length, MYF_RW)))
1455
 
      return(-1);
1456
 
 
1457
 
    write_begin= write_end;
1458
 
    if (write_end== current_position)
1459
 
      break;
1460
 
    else
1461
 
      file_buff->read_next(); /* shift the buffer */
1462
 
  }
1463
 
 
1464
 
  /*
1465
 
    Close the files and rename repaired file to the datafile.
1466
 
    We have to close the files, as on Windows one cannot rename
1467
 
    a file, which descriptor is still open. EACCES will be returned
1468
 
    when trying to delete the "to"-file in my_rename().
1469
 
  */
1470
 
  if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1471
 
      my_rename(repaired_fname, share->data_file_name, MYF(0)))
1472
 
    return(-1);
1473
 
 
1474
 
  /* Open the file again, it should now be repaired */
1475
 
  if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1476
 
                          MYF(0))) == -1)
1477
 
     return(-1);
1478
 
 
1479
 
  /* Set new file size. The file size will be updated by ::update_status() */
1480
 
  local_saved_data_file_length= (size_t) current_position;
1481
 
 
1482
 
end:
1483
 
  share->crashed= false;
1484
 
  return(HA_ADMIN_OK);
1485
 
}
1486
 
 
1487
 
/*
1488
1334
  DELETE without WHERE calls this
1489
1335
*/
1490
1336
 
1512
1358
}
1513
1359
 
1514
1360
/*
1515
 
  Called by the database to lock the table. Keep in mind that this
1516
 
  is an internal lock.
1517
 
*/
1518
 
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1519
 
                                    THR_LOCK_DATA **to,
1520
 
                                    enum thr_lock_type lock_type)
1521
 
{
1522
 
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
1523
 
    lock.type=lock_type;
1524
 
  *to++= &lock;
1525
 
  return to;
1526
 
}
1527
 
 
1528
 
/*
1529
1361
  Create a table. You do not want to leave the table open after a call to
1530
1362
  this (the database will call ::open() if it needs to).
1531
1363
*/
1572
1404
  return 0;
1573
1405
}
1574
1406
 
1575
 
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1576
 
{
1577
 
  int rc= 0;
1578
 
  unsigned char *buf;
1579
 
  const char *old_proc_info;
1580
 
  ha_rows count= share->rows_recorded;
1581
 
 
1582
 
  old_proc_info= get_session_proc_info(session);
1583
 
  set_session_proc_info(session, "Checking table");
1584
 
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1585
 
    return(HA_ERR_OUT_OF_MEM);
1586
 
 
1587
 
  /* position buffer to the start of the file */
1588
 
   if (init_data_file())
1589
 
     return(HA_ERR_CRASHED);
1590
 
 
1591
 
  /*
1592
 
    Local_saved_data_file_length is initialized during the lock phase.
1593
 
    Check does not use store_lock in certain cases. So, we set it
1594
 
    manually here.
1595
 
  */
1596
 
  local_saved_data_file_length= share->saved_data_file_length;
1597
 
  /* set current position to the beginning of the file */
1598
 
  current_position= next_position= 0;
1599
 
 
1600
 
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
1601
 
 
1602
 
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1603
 
  while (!(rc= find_current_row(buf)))
1604
 
  {
1605
 
    session_inc_row_count(session);
1606
 
    count--;
1607
 
    current_position= next_position;
1608
 
  }
1609
 
 
1610
 
  free_root(&blobroot, MYF(0));
1611
 
 
1612
 
  free((char*)buf);
1613
 
  set_session_proc_info(session, old_proc_info);
1614
 
 
1615
 
  if ((rc != HA_ERR_END_OF_FILE) || count)
1616
 
  {
1617
 
    share->crashed= true;
1618
 
    return(HA_ADMIN_CORRUPT);
1619
 
  }
1620
 
  else
1621
 
    return(HA_ADMIN_OK);
1622
 
}
1623
 
 
1624
1407
 
1625
1408
drizzle_declare_plugin
1626
1409
{