TRI_query_node_t* TRI_ParseQueryContextPop (TRI_query_template_t* const template_) { TRI_query_node_t* head; size_t i; i = template_->_memory._listHeads._length; if (i > 0) { TRI_RemoveVectorPointer(&template_->_memory._listTails, i - 1); head = TRI_RemoveVectorPointer(&template_->_memory._listHeads, i - 1); return head; } return 0; }
static int RemoveDatafile (TRI_document_collection_t* document, TRI_datafile_t* df) { TRI_primary_collection_t* primary; TRI_doc_datafile_info_t* dfi; size_t i; primary = &document->base; LOG_TRACE("removing empty datafile '%s'", df->getName(df)); // remove the datafile from the list of datafiles TRI_WRITE_LOCK_DATAFILES_DOC_COLLECTION(primary); if (! LocateDatafile(&primary->base._datafiles, df->_fid, &i)) { TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); LOG_ERROR("logic error: could not locate datafile"); return TRI_ERROR_INTERNAL; } TRI_RemoveVectorPointer(&primary->base._datafiles, i); // update dfi dfi = TRI_FindDatafileInfoPrimaryCollection(primary, df->_fid, false); if (dfi != NULL) { TRI_RemoveDatafileInfoPrimaryCollection(primary, df->_fid); TRI_Free(TRI_UNKNOWN_MEM_ZONE, dfi); } TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); return TRI_ERROR_NO_ERROR; }
bool TRI_KillExternalProcess (TRI_external_id_t pid) { TRI_external_t* external = nullptr; // just to please the compiler size_t i; bool ok = true; LOG_DEBUG("killing process: %d", (int) pid._pid); TRI_LockMutex(&ExternalProcessesLock); for (i = 0; i < ExternalProcesses._length; ++i) { external = static_cast<TRI_external_t*>(TRI_AtVectorPointer(&ExternalProcesses, i)); if (external->_pid == pid._pid) { break; } } if (i == ExternalProcesses._length) { TRI_UnlockMutex(&ExternalProcessesLock); LOG_DEBUG("kill: process not found: %d", (int) pid._pid); #ifndef _WIN32 // Kill just in case: if (0 == kill(pid._pid, SIGTERM)) { int count; // Otherwise we just let it be. for (count = 0; count < 10; count++) { int loc; pid_t p; // And wait for it to avoid a zombie: sleep(1); p = waitpid(pid._pid, &loc, WUNTRACED | WNOHANG); if (p == pid._pid) { return true; } if (count == 8) { kill(pid._pid, SIGKILL); } } } return false; #else return ourKillProcessPID(pid._pid); #endif } if (external->_status == TRI_EXT_RUNNING || external->_status == TRI_EXT_STOPPED) { ok = ourKillProcess(external); } TRI_RemoveVectorPointer(&ExternalProcesses, i); TRI_UnlockMutex(&ExternalProcessesLock); FreeExternal(external); return ok; }
static void RunWalk (TRI_aql_statement_walker_t* const walker) { size_t i, n; assert(walker); n = walker->_statements->_statements._length; for (i = 0; i < n; ++i) { TRI_aql_node_t* node; TRI_aql_node_type_e nodeType; node = (TRI_aql_node_t*) TRI_AtVectorPointer(&walker->_statements->_statements, i); if (!node) { continue; } nodeType = node->_type; // handle scopes if (nodeType == TRI_AQL_NODE_SCOPE_START) { TRI_PushBackVectorPointer(&walker->_currentScopes, TRI_AQL_NODE_DATA(node)); } // preprocess node if (walker->preVisitStatement != NULL) { // this might change the node ptr VisitStatement(walker, i, walker->preVisitStatement); node = walker->_statements->_statements._buffer[i]; } // process node's members if (walker->visitMember != NULL) { VisitMembers(walker, node); } // post process node if (walker->postVisitStatement != NULL) { VisitStatement(walker, i, walker->postVisitStatement); } if (nodeType == TRI_AQL_NODE_SCOPE_END) { size_t len = walker->_currentScopes._length; assert(len > 0); TRI_RemoveVectorPointer(&walker->_currentScopes, len - 1); } } }
void TRI_FreeNodeVectorQuery (TRI_vector_pointer_t* const memory) { void* nodePtr; size_t i; i = memory->_length; // free all nodes in vector, starting at the end // (prevents copying the remaining elements in vector) while (i > 0) { i--; nodePtr = TRI_RemoveVectorPointer(memory, i); TRI_FreeNodeQuery(nodePtr); if (i == 0) { break; } } TRI_DestroyVectorPointer(memory); }
static TRI_aql_node_t* FixAttributeAccess (TRI_aql_statement_walker_t* const walker, TRI_aql_node_t* node) { TRI_aql_context_t* context; TRI_aql_node_t* valueNode; char* stringValue; if (node == NULL || node->_type != TRI_AQL_NODE_BOUND_ATTRIBUTE_ACCESS) { return node; } // we found a bound attribute access context = (TRI_aql_context_t*) walker->_data; assert(context); assert(node->_members._length == 2); valueNode = TRI_AQL_NODE_MEMBER(node, 1); if (valueNode == NULL) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return node; } if (valueNode->_type != TRI_AQL_NODE_VALUE || valueNode->_value._type != TRI_AQL_TYPE_STRING) { TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, "(unknown)"); return node; } stringValue = TRI_AQL_NODE_STRING(valueNode); if (stringValue == NULL || strlen(stringValue) == 0) { TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, "(unknown)"); return node; } // remove second node TRI_RemoveVectorPointer(&node->_members, 1); // set attribute name TRI_AQL_NODE_STRING(node) = stringValue; // convert node type node->_type = TRI_AQL_NODE_ATTRIBUTE_ACCESS; return node; }
static int RemoveCompactor (TRI_document_collection_t* document, TRI_datafile_t* compactor) { TRI_primary_collection_t* primary; size_t i; primary = &document->base; LOG_TRACE("removing empty compaction file '%s'", compactor->getName(compactor)); // remove the datafile from the list of datafiles TRI_WRITE_LOCK_DATAFILES_DOC_COLLECTION(primary); // remove the compactor from the list of compactors if (! LocateDatafile(&primary->base._compactors, compactor->_fid, &i)) { TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); LOG_ERROR("logic error: could not locate compactor"); return TRI_ERROR_INTERNAL; } TRI_RemoveVectorPointer(&primary->base._compactors, i); TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); // close the file & remove it if (compactor->isPhysical(compactor)) { char* filename; filename = TRI_DuplicateString(compactor->getName(compactor)); TRI_CloseDatafile(compactor); TRI_FreeDatafile(compactor); TRI_UnlinkFile(filename); TRI_Free(TRI_CORE_MEM_ZONE, filename); } else { TRI_CloseDatafile(compactor); TRI_FreeDatafile(compactor); } return TRI_ERROR_NO_ERROR; }
void TRI_FreeStringVectorQuery (TRI_vector_pointer_t* const memory) { char* stringPtr; size_t i; i = memory->_length; // free all strings in vector, starting at the end // (prevents copying the remaining elements in vector) while (i > 0) { i--; stringPtr = TRI_RemoveVectorPointer(memory, i); if (stringPtr) { TRI_Free(stringPtr); stringPtr = NULL; } if (i == 0) { break; } } TRI_DestroyVectorPointer(memory); }
bool TRI_EndScopeByReturnAql (TRI_aql_context_t* const context) { TRI_aql_scope_e type; TRI_aql_node_t* node; size_t n; assert(context); type = CurrentType(context); if (type == TRI_AQL_SCOPE_MAIN || type == TRI_AQL_SCOPE_SUBQUERY) { return true; } n = context->_currentScopes._length; assert(n > 0); while (n > 0) { TRI_aql_scope_t* scope; scope = (TRI_aql_scope_t*) TRI_RemoveVectorPointer(&context->_currentScopes, --n); assert(scope); LOG_TRACE("closing scope of type %s", TRI_TypeNameScopeAql(scope->_type)); node = TRI_CreateNodeScopeEndAql(context, scope); if (node == NULL) { return false; } if (! TRI_AppendStatementListAql(context->_statements, node)) { return false; } if (scope->_type != TRI_AQL_SCOPE_FOR_NESTED) { // removed enough scopes break; } } return true; }
static TRI_aql_node_t* OptimiseSort (TRI_aql_statement_walker_t* const walker, TRI_aql_node_t* node) { TRI_aql_node_t* list = TRI_AQL_NODE_MEMBER(node, 0); size_t i, n; if (!list) { return node; } i = 0; n = list->_members._length; while (i < n) { // sort element TRI_aql_node_t* element = TRI_AQL_NODE_MEMBER(list, i); TRI_aql_node_t* expression = TRI_AQL_NODE_MEMBER(element, 0); // check if the sort element is constant if (!expression || !TRI_IsConstantValueNodeAql(expression)) { ++i; continue; } // sort element is constant so it can be removed TRI_RemoveVectorPointer(&list->_members, i); --n; LOG_TRACE("optimised away sort element"); } if (n == 0) { // no members left => sort removed LOG_TRACE("optimised away sort"); return TRI_GetDummyNopNodeAql(); } return node; }
bool TRI_EndScopeAql (TRI_aql_context_t* const context) { TRI_aql_scope_t* scope; TRI_aql_node_t* node; size_t n; assert(context); n = context->_currentScopes._length; assert(n > 0); scope = TRI_RemoveVectorPointer(&context->_currentScopes, --n); LOG_TRACE("closing scope of type %s", TRI_TypeNameScopeAql(scope->_type)); node = TRI_CreateNodeScopeEndAql(context, scope); if (node == NULL) { return false; } if (! TRI_AppendStatementListAql(context->_statements, node)) { return false; } return true; }
static void RenameDatafileCallback (TRI_datafile_t* datafile, void* data) { compaction_context_t* context; TRI_datafile_t* compactor; TRI_primary_collection_t* primary; bool ok; context = data; compactor = context->_compactor; primary = &context->_document->base; ok = false; assert(datafile->_fid == compactor->_fid); if (datafile->isPhysical(datafile)) { char* number; char* jname; char* tempFilename; char* realName; realName = TRI_DuplicateString(datafile->_filename); // construct a suitable tempname number = TRI_StringUInt64(datafile->_fid); jname = TRI_Concatenate3String("temp-", number, ".db"); tempFilename = TRI_Concatenate2File(primary->base._directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); if (! TRI_RenameDatafile(datafile, tempFilename)) { LOG_ERROR("unable to rename datafile '%s' to '%s'", datafile->getName(datafile), tempFilename); } else { if (! TRI_RenameDatafile(compactor, realName)) { LOG_ERROR("unable to rename compaction file '%s' to '%s'", compactor->getName(compactor), realName); } else { ok = true; } } TRI_FreeString(TRI_CORE_MEM_ZONE, tempFilename); TRI_FreeString(TRI_CORE_MEM_ZONE, realName); } else { ok = true; } if (ok) { TRI_doc_datafile_info_t* dfi; size_t i; // must acquire a write-lock as we're about to change the datafiles vector TRI_WRITE_LOCK_DATAFILES_DOC_COLLECTION(primary); if (! LocateDatafile(&primary->base._datafiles, datafile->_fid, &i)) { TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); LOG_ERROR("logic error: could not locate datafile"); return; } // put the compactor in place of the datafile primary->base._datafiles._buffer[i] = compactor; // update dfi dfi = TRI_FindDatafileInfoPrimaryCollection(primary, compactor->_fid, false); if (dfi != NULL) { memcpy(dfi, &context->_dfi, sizeof(TRI_doc_datafile_info_t)); } else { LOG_ERROR("logic error: could not find compactor file information"); } if (! LocateDatafile(&primary->base._compactors, compactor->_fid, &i)) { TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); LOG_ERROR("logic error: could not locate compactor"); return; } // remove the compactor from the list of compactors TRI_RemoveVectorPointer(&primary->base._compactors, i); TRI_WRITE_UNLOCK_DATAFILES_DOC_COLLECTION(primary); DropDatafileCallback(datafile, primary); } TRI_Free(TRI_CORE_MEM_ZONE, context); }
static void CompactifyDatafile (TRI_sim_collection_t* sim, TRI_voc_fid_t fid) { TRI_datafile_t* df; bool ok; size_t n; size_t i; // locate the datafile TRI_READ_LOCK_DATAFILES_SIM_COLLECTION(sim); n = sim->base.base._datafiles._length; for (i = 0; i < n; ++i) { df = sim->base.base._datafiles._buffer[i]; if (df->_fid == fid) { break; } } TRI_READ_UNLOCK_DATAFILES_SIM_COLLECTION(sim); if (i == n) { return; } // now compactify the datafile LOG_DEBUG("starting to compactify datafile '%s'", df->_filename); ok = TRI_IterateDatafile(df, Compactifier, sim, false); if (! ok) { LOG_WARNING("failed to compactify the datafile '%s'", df->_filename); return; } // wait for the journals to sync WaitCompactSync(sim, df); // remove the datafile from the list of datafiles TRI_WRITE_LOCK_DATAFILES_SIM_COLLECTION(sim); n = sim->base.base._datafiles._length; for (i = 0; i < n; ++i) { df = sim->base.base._datafiles._buffer[i]; if (df->_fid == fid) { TRI_RemoveVectorPointer(&sim->base.base._datafiles, i); break; } } TRI_WRITE_UNLOCK_DATAFILES_SIM_COLLECTION(sim); if (i == n) { LOG_WARNING("failed to locate the datafile '%lu'", (unsigned long) df->_fid); return; } // add a deletion marker to the result set container TRI_CreateBarrierDatafile(&sim->base._barrierList, df, RemoveDatafileCallback, &sim->base.base); }
void* TRI_PopStackParseAql (TRI_aql_context_t* const context) { assert(context); assert(context->_parser->_stack._length > 0); return TRI_RemoveVectorPointer(&context->_parser->_stack, context->_parser->_stack._length - 1); }
static bool CloseJournalPrimaryCollection (TRI_primary_collection_t* primary, size_t position, bool compactor) { TRI_datafile_t* journal; TRI_collection_t* collection; TRI_vector_pointer_t* vector; int res; collection = &primary->base; // either use a journal or a compactor if (compactor) { vector = &collection->_compactors; } else { vector = &collection->_journals; } // no journal at this position if (vector->_length <= position) { TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); return false; } // seal and rename datafile journal = vector->_buffer[position]; res = TRI_SealDatafile(journal); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("failed to seal datafile '%s': %s", journal->getName(journal), TRI_last_error()); TRI_RemoveVectorPointer(vector, position); TRI_PushBackVectorPointer(&collection->_datafiles, journal); return false; } if (journal->isPhysical(journal)) { // rename the file char* dname; char* filename; char* number; bool ok; number = TRI_StringUInt64(journal->_fid); dname = TRI_Concatenate3String("datafile-", number, ".db"); filename = TRI_Concatenate2File(collection->_directory, dname); TRI_FreeString(TRI_CORE_MEM_ZONE, dname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); ok = TRI_RenameDatafile(journal, filename); if (! ok) { LOG_ERROR("failed to rename datafile '%s' to '%s': %s", journal->getName(journal), filename, TRI_last_error()); TRI_RemoveVectorPointer(vector, position); TRI_PushBackVectorPointer(&collection->_datafiles, journal); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return false; } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); LOG_TRACE("closed journal '%s'", journal->getName(journal)); } TRI_RemoveVectorPointer(vector, position); TRI_PushBackVectorPointer(&collection->_datafiles, journal); return true; }
TRI_external_status_t TRI_CheckExternalProcess (TRI_external_id_t pid, bool wait) { TRI_external_status_t status; TRI_external_t* external = nullptr; // Just to please the compiler size_t i; TRI_LockMutex(&ExternalProcessesLock); status._status = TRI_EXT_NOT_FOUND; status._exitStatus = 0; for (i = 0; i < ExternalProcesses._length; ++i) { external = static_cast<TRI_external_t*>(TRI_AtVectorPointer(&ExternalProcesses, i)); if (external->_pid == pid._pid) { break; } } if (i == ExternalProcesses._length) { TRI_UnlockMutex(&ExternalProcessesLock); status._errorMessage = std::string("the pid you're looking for is not in our list: ") + triagens::basics::StringUtils::itoa(static_cast<int64_t>(pid._pid)); status._status = TRI_EXT_NOT_FOUND; LOG_WARNING("checkExternal: pid not found: %d", (int) pid._pid); return status; } if (external->_status == TRI_EXT_RUNNING || external->_status == TRI_EXT_STOPPED) { #ifndef _WIN32 TRI_pid_t res; int opts; int loc = 0; if (wait) { opts = WUNTRACED; } else { opts = WNOHANG | WUNTRACED; } res = waitpid(external->_pid, &loc, opts); if (res == 0) { if (wait) { status._errorMessage = std::string("waitpid returned 0 for pid while it shouldn't ") + triagens::basics::StringUtils::itoa(external->_pid); if (WIFEXITED(loc)) { external->_status = TRI_EXT_TERMINATED; external->_exitStatus = WEXITSTATUS(loc); } else if (WIFSIGNALED(loc)) { external->_status = TRI_EXT_ABORTED; external->_exitStatus = WTERMSIG(loc); } else if (WIFSTOPPED(loc)) { external->_status = TRI_EXT_STOPPED; external->_exitStatus = 0; } else { external->_status = TRI_EXT_ABORTED; external->_exitStatus = 0; } } else { external->_exitStatus = 0; } } else if (res == -1) { TRI_set_errno(TRI_ERROR_SYS_ERROR); LOG_WARNING("waitpid returned error for pid %d (%d): %s", (int) external->_pid, (int) wait, TRI_last_error()); status._errorMessage = std::string("waitpid returned error for pid ") + triagens::basics::StringUtils::itoa(external->_pid) + std::string(": ") + std::string(TRI_last_error()); } else if (static_cast<TRI_pid_t>(external->_pid) == static_cast<TRI_pid_t>(res)) { if (WIFEXITED(loc)) { external->_status = TRI_EXT_TERMINATED; external->_exitStatus = WEXITSTATUS(loc); } else if (WIFSIGNALED(loc)) { external->_status = TRI_EXT_ABORTED; external->_exitStatus = WTERMSIG(loc); } else if (WIFSTOPPED(loc)) { external->_status = TRI_EXT_STOPPED; external->_exitStatus = 0; } else { external->_status = TRI_EXT_ABORTED; external->_exitStatus = 0; } } else { LOG_WARNING("unexpected waitpid result for pid %d: %d", (int) external->_pid, (int) res); status._errorMessage = std::string("unexpected waitpid result for pid ") + triagens::basics::StringUtils::itoa(external->_pid) + std::string(": ") + triagens::basics::StringUtils::itoa(res); } #else { char windowsErrorBuf[256]; bool wantGetExitCode = wait; if (wait) { DWORD result; result = WaitForSingleObject(external->_process, INFINITE); if (result == WAIT_FAILED) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, windowsErrorBuf, sizeof(windowsErrorBuf), NULL); LOG_WARNING("could not wait for subprocess with PID '%ud': %s", (unsigned int) external->_pid, windowsErrorBuf); status._errorMessage = std::string("could not wait for subprocess with PID '") + triagens::basics::StringUtils::itoa(static_cast<int64_t>(external->_pid)) + std::string("'") + windowsErrorBuf; status._exitStatus = GetLastError(); } } else { DWORD result; result = WaitForSingleObject(external->_process, 0); switch (result) { case WAIT_ABANDONED: wantGetExitCode = true; LOG_WARNING("WAIT_ABANDONED while waiting for subprocess with PID '%ud'", (unsigned int)external->_pid); break; case WAIT_OBJECT_0: /// this seems to be the exit case - want getExitCodeProcess here. wantGetExitCode = true; break; case WAIT_TIMEOUT: // success - everything went well. external->_exitStatus = 0; break; case WAIT_FAILED: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, windowsErrorBuf, sizeof(windowsErrorBuf), NULL); LOG_WARNING("could not wait for subprocess with PID '%ud': %s", (unsigned int)external->_pid, windowsErrorBuf); status._errorMessage = std::string("could not wait for subprocess with PID '") + triagens::basics::StringUtils::itoa(static_cast<int64_t>(external->_pid)) + std::string("'") + windowsErrorBuf; status._exitStatus = GetLastError(); default: wantGetExitCode = true; LOG_WARNING("unexpected status while waiting for subprocess with PID '%ud'", (unsigned int)external->_pid); } } if (wantGetExitCode) { DWORD exitCode = STILL_ACTIVE; if (!GetExitCodeProcess(external->_process, &exitCode)) { LOG_WARNING("exit status could not be determined for PID '%ud'", (unsigned int)external->_pid); status._errorMessage = std::string("exit status could not be determined for PID '") + triagens::basics::StringUtils::itoa(static_cast<int64_t>(external->_pid)) + std::string("'"); } else { if (exitCode == STILL_ACTIVE) { external->_exitStatus = 0; } else if (exitCode > 255) { // this should be one of our signals which we mapped... external->_status = TRI_EXT_ABORTED; external->_exitStatus = exitCode - 255; } else { external->_status = TRI_EXT_TERMINATED; external->_exitStatus = exitCode; } } } else { external->_status = TRI_EXT_RUNNING; } } #endif } else { LOG_WARNING("unexpected process status %d: %d", (int) external->_status, (int) external->_exitStatus); status._errorMessage = std::string("unexpected process status ") + triagens::basics::StringUtils::itoa(external->_status) + std::string(": ") + triagens::basics::StringUtils::itoa(external->_exitStatus); } status._status = external->_status; status._exitStatus = external->_exitStatus; // Do we have to free our data? if (external->_status != TRI_EXT_RUNNING && external->_status != TRI_EXT_STOPPED) { TRI_RemoveVectorPointer(&ExternalProcesses, i); FreeExternal(external); } TRI_UnlockMutex(&ExternalProcessesLock); return status; }
static bool CloseJournal (TRI_shape_collection_t* collection, TRI_datafile_t* journal) { int res; size_t i; size_t n; // remove datafile from list of journals n = collection->base._journals._length; for (i = 0; i < n; ++i) { TRI_datafile_t* df; df = collection->base._journals._buffer[i]; if (journal == df) { break; } } if (i == n) { TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); return false; } // seal datafile res = TRI_SealDatafile(journal); if (res != TRI_ERROR_NO_ERROR) { collection->base._state = TRI_COL_STATE_WRITE_ERROR; return false; } // rename datafile if (journal->isPhysical(journal)) { char* dname; char* filename; char* number; bool ok; number = TRI_StringUInt32(journal->_fid); dname = TRI_Concatenate3String("datafile-", number, ".db"); filename = TRI_Concatenate2File(collection->base._directory, dname); TRI_FreeString(TRI_CORE_MEM_ZONE, dname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); ok = TRI_RenameDatafile(journal, filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); if (! ok) { collection->base._state = TRI_COL_STATE_WRITE_ERROR; return false; } } LOG_TRACE("closed journal '%s'", journal->getName(journal)); TRI_RemoveVectorPointer(&collection->base._journals, i); TRI_PushBackVectorPointer(&collection->base._datafiles, journal); return true; }