static alice_str* alloc_string(const TEXT** ptr) { AliceGlobals* tdgbl = AliceGlobals::getSpecific(); const TEXT* p = *ptr; const USHORT length = (USHORT) *p++; alice_str* string = FB_NEW_RPT(*tdgbl->getDefaultPool(), length + 1) alice_str; memcpy(string->str_data, p, length); string->str_data[length] = 0; *ptr = p + length; return string; }
static void parse_fullpath(tdr* trans) { AliceGlobals* tdgbl = AliceGlobals::getSpecific(); // start at the end of the full pathname const TEXT* p = (TEXT*) trans->tdr_fullpath->str_data; const TEXT* const start = p; while (*p) p++; const TEXT* const end = p; // Check for a named pipes name - \\node\path\db or //node/path/db while (p > start && !(*p == '/' && p[-1] == '/') && !(*p == '\\' && p[-1] == '\\')) { --p; } if (p > start) { // Increment p past slash, & search forward for end of node name p = p + 1; const TEXT* q = p; while (*q && *q != '/' && *q != '\\') q++; if (*q) { trans->tdr_filename = q + 1; trans->tdr_remote_site = FB_NEW_RPT(*tdgbl->getDefaultPool(), q - p + 1) alice_str; strncpy((char*) trans->tdr_remote_site->str_data, (char*) p, q - p); trans->tdr_remote_site->str_data[q - p] = '\0'; } } else { p = end; // If not named pipes, check the other protocols // work backwards until we find a remote protocol specifier while (p >= start && (*p != '^' && *p != ':' && *p != '@')) p--; // dimitr: make sure that the remote path is parsed correctly // for win32 servers, i.e. the drive separator is taken into account if ((p - 2 >= start) && p[-2] == ':' && (p[0] == ':')) p -= 2; trans->tdr_filename = p + 1; // now find the last remote node in the chain while (p > start && (*p == ':' || *p == '^' || *p == '@')) p--; USHORT length = 0; for (; p >= start && (*p != '^' && *p != ':' && *p != '@'); ++length) --p; ++p; if (length) { trans->tdr_remote_site = FB_NEW_RPT(*tdgbl->getDefaultPool(), length + 1) alice_str; TEXT* q = (TEXT *) trans->tdr_remote_site->str_data; while (length--) *q++ = *p++; *q = 0; } } }
static tdr* get_description(ISC_QUAD* blob_id) { TEXT buffer[1024]; TEXT* bigger_buffer = 0; AliceGlobals* tdgbl = AliceGlobals::getSpecific(); const TEXT* p = buffer; const USHORT length = snarf_blob(blob_id, (USHORT) sizeof(buffer), buffer); if (length) { p = bigger_buffer = (TEXT *) gds__alloc((SLONG) length); if (!p) { tdgbl->status[0] = isc_arg_gds; tdgbl->status[1] = isc_virmemexh; tdgbl->status[2] = isc_arg_end; ALICE_print_status(true, tdgbl->status); return NULL; } snarf_blob(blob_id, length, bigger_buffer); } tdr* trans = NULL; alice_str* host_site = NULL; alice_str* database_path = NULL; // skip version number ++p; tdr* ptr = NULL; // silence uninitialized warning SLONG id_length, id; while (*p) { switch (*p++) { case TDR_HOST_SITE: host_site = alloc_string(&p); break; case TDR_DATABASE_PATH: database_path = alloc_string(&p); break; case TDR_TRANSACTION_ID: id_length = *p++; id = gds__vax_integer(reinterpret_cast<const UCHAR*>(p), id_length); p += id_length; if (!trans) { trans = ptr = FB_NEW(*tdgbl->getDefaultPool()) tdr; } else { ptr->tdr_next = FB_NEW(*tdgbl->getDefaultPool()) tdr; ptr = ptr->tdr_next; } ptr->tdr_host_site = host_site; ptr->tdr_fullpath = database_path; parse_fullpath(ptr); ptr->tdr_id = id; database_path = NULL; break; default: ALICE_print(108); // msg 108: Transaction description item unknown. if (length) { gds__free(bigger_buffer); } return NULL; } } if (length) { gds__free(bigger_buffer); } return trans; }
static void reattach_database(tdr* trans) { ISC_STATUS_ARRAY status_vector; char buffer[1024]; // sizeof(buffer) - 1 => leave space for the terminator. const char* const end = buffer + sizeof(buffer) - 1; AliceGlobals* tdgbl = AliceGlobals::getSpecific(); ISC_get_host(buffer, sizeof(buffer)); if (trans->tdr_fullpath) { // if this is being run from the same host, // try to reconnect using the same pathname if (!strcmp(buffer, reinterpret_cast<const char*>(trans->tdr_host_site->str_data))) { if (TDR_attach_database(status_vector, trans, reinterpret_cast<char*>(trans->tdr_fullpath->str_data))) { return; } } else if (trans->tdr_host_site) { // try going through the previous host with all available // protocols, using chaining to try the same method of // attachment originally used from that host char* p = buffer; const UCHAR* q = trans->tdr_host_site->str_data; while (*q && p < end) *p++ = *q++; *p++ = ':'; q = trans->tdr_fullpath->str_data; while (*q && p < end) *p++ = *q++; *p = 0; if (TDR_attach_database(status_vector, trans, buffer)) { return; } } // attaching using the old method didn't work; // try attaching to the remote node directly if (trans->tdr_remote_site) { char* p = buffer; const UCHAR* q = trans->tdr_remote_site->str_data; while (*q && p < end) *p++ = *q++; *p++ = ':'; q = reinterpret_cast<const UCHAR*>(trans->tdr_filename); while (*q && p < end) *p++ = *q++; *p = 0; if (TDR_attach_database (status_vector, trans, buffer)) { return; } } } // we have failed to reattach; notify the user // and let them try to succeed where we have failed ALICE_print(86, SafeArg() << trans->tdr_id); // msg 86: Could not reattach to database for transaction %ld. ALICE_print(87, SafeArg() << (trans->tdr_fullpath ? (char*)(trans->tdr_fullpath->str_data) : "is unknown")); // msg 87: Original path: %s if (tdgbl->uSvc->isService()) { ALICE_exit(FINI_ERROR, tdgbl); } for (;;) { ALICE_print(88); // msg 88: Enter a valid path: char* p = buffer; while (p < end && (*p = getchar()) != '\n' && !feof(stdin) && !ferror(stdin)) ++p; *p = 0; if (!buffer[0]) break; p = buffer; while (*p == ' ') ++p; if (TDR_attach_database(status_vector, trans, p)) { const size_t p_len = strlen(p); alice_str* string = FB_NEW_RPT(*tdgbl->getDefaultPool(), p_len + 1) alice_str; strcpy(reinterpret_cast<char*>(string->str_data), p); string->str_length = static_cast<USHORT>(p_len); trans->tdr_fullpath = string; trans->tdr_filename = (TEXT *) string->str_data; return; } ALICE_print(89); // msg 89: Attach unsuccessful. } }