+ Pmsg2(-1, _("We should be in file 3. I am at file %d. This is %s\n"),
+ dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!");
+
+ if (dev->file != 3) {
+ return -1;
+ }
+
+ Pmsg0(-1, _("\nNow the important part, I am going to attempt to append to the tape.\n\n"));
+ wrcmd();
+ weofcmd();
+ if (dev_cap(dev, CAP_TWOEOF)) {
+ weofcmd();
+ }
+ rewindcmd();
+ Pmsg0(-1, _("Done appending, there should be no I/O errors\n\n"));
+ Pmsg0(-1, "Doing Bacula scan of blocks:\n");
+ scan_blocks();
+ Pmsg0(-1, _("End scanning the tape.\n"));
+ Pmsg2(-1, _("We should be in file 4. I am at file %d. This is %s\n"),
+ dev->file, dev->file == 4 ? "correct!" : "NOT correct!!!!");
+
+ if (dev->file != 4) {
+ return -2;
+ }
+ return 1;
+}
+
+
+/*
+ * This test exercises the autochanger
+ */
+static int autochanger_test()
+{
+ POOLMEM *results, *changer;
+ int slot, status, loaded;
+ int timeout = dcr->device->max_changer_wait;
+ int sleep_time = 0;
+
+ Dmsg1(100, "Max changer wait = %d sec\n", timeout);
+ if (!dev_cap(dev, CAP_AUTOCHANGER)) {
+ return 1;
+ }
+ if (!(dcr->device && dcr->device->changer_name && dcr->device->changer_command)) {
+ Pmsg0(-1, "\nAutochanger enabled, but no name or no command device specified.\n");
+ return 1;
+ }
+
+ Pmsg0(-1, "\nAh, I see you have an autochanger configured.\n"
+ "To test the autochanger you must have a blank tape\n"
+ " that I can write on in Slot 1.\n");
+ if (!get_cmd("\nDo you wish to continue with the Autochanger test? (y/n): ")) {
+ return 0;
+ }
+ if (cmd[0] != 'y' && cmd[0] != 'Y') {
+ return 0;
+ }
+
+ Pmsg0(-1, _("\n\n=== Autochanger test ===\n\n"));
+
+ results = get_pool_memory(PM_MESSAGE);
+ changer = get_pool_memory(PM_FNAME);
+
+try_again:
+ slot = 1;
+ dcr->VolCatInfo.Slot = slot;
+ /* Find out what is loaded, zero means device is unloaded */
+ Pmsg0(-1, _("3301 Issuing autochanger \"loaded\" command.\n"));
+ changer = edit_device_codes(dcr, changer, "loaded");
+ status = run_program(changer, timeout, results);
+ Dmsg3(100, "run_prog: %s stat=%d result=\"%s\"\n", changer, status, results);
+ if (status == 0) {
+ loaded = atoi(results);
+ } else {
+ berrno be;
+ Pmsg1(-1, _("3991 Bad autochanger command: %s\n"), changer);
+ Pmsg2(-1, _("3991 result=\"%s\": ERR=%s\n"), results, be.strerror(status));
+ goto bail_out;
+ }
+ if (loaded) {
+ Pmsg1(-1, "Slot %d loaded. I am going to unload it.\n", loaded);
+ } else {
+ Pmsg0(-1, "Nothing loaded in the drive. OK.\n");
+ }
+ Dmsg1(100, "Results from loaded query=%s\n", results);
+ if (loaded) {
+ dcr->VolCatInfo.Slot = loaded;
+ offline_or_rewind_dev(dev);
+ /* We are going to load a new tape, so close the device */
+ force_close_dev(dev);
+ Pmsg2(-1, _("3302 Issuing autochanger \"unload %d %d\" command.\n"),
+ loaded, dev->drive_index);
+ changer = edit_device_codes(dcr, changer, "unload");
+ status = run_program(changer, timeout, results);
+ Pmsg2(-1, "unload status=%s %d\n", status==0?"OK":"Bad", status);
+ if (status != 0) {
+ berrno be;
+ Pmsg1(-1, _("3992 Bad autochanger command: %s\n"), changer);
+ Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.strerror(status));
+ }
+ }
+
+ /*
+ * Load the Slot 1
+ */
+
+ slot = 1;
+ dcr->VolCatInfo.Slot = slot;
+ Pmsg2(-1, _("3303 Issuing autochanger \"load slot %d %d\" command.\n"),
+ slot, dev->drive_index);
+ changer = edit_device_codes(dcr, changer, "load");
+ Dmsg1(100, "Changer=%s\n", changer);
+ force_close_dev(dev);
+ status = run_program(changer, timeout, results);
+ if (status == 0) {
+ Pmsg2(-1, _("3303 Autochanger \"load slot %d %d\" status is OK.\n"),
+ slot, dev->drive_index);
+ } else {
+ berrno be;
+ Pmsg1(-1, _("3993 Bad autochanger command: %s\n"), changer);
+ Pmsg2(-1, _("3993 result=\"%s\": ERR=%s\n"), results, be.strerror(status));
+ goto bail_out;
+ }
+
+ if (!open_the_device()) {
+ goto bail_out;
+ }
+ /*
+ * Start with sleep_time 0 then increment by 30 seconds if we get
+ * a failure.
+ */
+ bmicrosleep(sleep_time, 0);
+ if (!rewind_dev(dev) || weof_dev(dev,1) < 0) {
+ Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
+ clrerror_dev(dev, -1);
+ Pmsg0(-1, "\nThe test failed, probably because you need to put\n"
+ "a longer sleep time in the mtx-script in the load) case.\n"
+ "Adding a 30 second sleep and trying again ...\n");
+ sleep_time += 30;
+ goto try_again;
+ } else {
+ Pmsg1(0, "Rewound %s\n", dev->print_name());
+ }
+
+ if ((status = weof_dev(dev, 1)) < 0) {
+ Pmsg2(0, "Bad status from weof %d. ERR=%s\n", status, strerror_dev(dev));
+ goto bail_out;
+ } else {
+ Pmsg1(0, "Wrote EOF to %s\n", dev->print_name());
+ }
+
+ if (sleep_time) {
+ Pmsg1(-1, "\nThe test worked this time. Please add:\n\n"
+ " sleep %d\n\n"
+ "to your mtx-changer script in the load) case.\n\n",
+ sleep_time);
+ } else {
+ Pmsg0(-1, "\nThe test autochanger worked!!\n\n");
+ }
+
+ free_pool_memory(changer);
+ free_pool_memory(results);
+ return 1;
+
+
+bail_out:
+ free_pool_memory(changer);
+ free_pool_memory(results);
+ Pmsg0(-1, "You must correct this error or the Autochanger will not work.\n");
+ return -2;
+}
+
+static void autochangercmd()
+{
+ autochanger_test();
+}
+
+
+/*
+ * This test assumes that the append test has been done,
+ * then it tests the fsf function.
+ */
+static int fsf_test()
+{
+ bool set_off = false;
+
+ Pmsg0(-1, _("\n\n=== Forward space files test ===\n\n"
+ "This test is essential to Bacula.\n\n"
+ "I'm going to write five files then test forward spacing\n\n"));
+ argc = 1;
+ rewindcmd();
+ wrcmd();
+ weofcmd(); /* end file 0 */
+ wrcmd();
+ wrcmd();
+ weofcmd(); /* end file 1 */
+ wrcmd();
+ wrcmd();
+ wrcmd();
+ weofcmd(); /* end file 2 */
+ wrcmd();
+ wrcmd();
+ weofcmd(); /* end file 3 */
+ wrcmd();
+ weofcmd(); /* end file 4 */
+ if (dev_cap(dev, CAP_TWOEOF)) {
+ weofcmd();
+ }
+
+test_again:
+ rewindcmd();
+ Pmsg0(0, _("Now forward spacing 1 file.\n"));
+ if (!fsf_dev(dev, 1)) {
+ Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev));
+ goto bail_out;
+ }
+ Pmsg2(-1, _("We should be in file 1. I am at file %d. This is %s\n"),
+ dev->file, dev->file == 1 ? "correct!" : "NOT correct!!!!");
+
+ if (dev->file != 1) {
+ goto bail_out;
+ }
+
+ Pmsg0(0, _("Now forward spacing 2 files.\n"));
+ if (!fsf_dev(dev, 2)) {
+ Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev));
+ goto bail_out;
+ }
+ Pmsg2(-1, _("We should be in file 3. I am at file %d. This is %s\n"),