char* TRI_GetDirectoryCollection (char const* path, const TRI_col_info_t* const parameter) { char* filename; assert(path); assert(parameter); // shape collections use just the name, e.g. path/SHAPES if (parameter->_type == TRI_COL_TYPE_SHAPE) { filename = TRI_Concatenate2File(path, parameter->_name); } // other collections use the collection identifier else if (TRI_IS_DOCUMENT_COLLECTION(parameter->_type)) { char* tmp1; char* tmp2; tmp1 = TRI_StringUInt64(parameter->_cid); if (tmp1 == NULL) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); return NULL; } tmp2 = TRI_Concatenate2String("collection-", tmp1); if (tmp2 == NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1); TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); return NULL; } filename = TRI_Concatenate2File(path, tmp2); TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1); TRI_FreeString(TRI_CORE_MEM_ZONE, tmp2); } // oops, unknown collection type else { TRI_set_errno(TRI_ERROR_ARANGO_UNKNOWN_COLLECTION_TYPE); return NULL; } if (filename == NULL) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); } // might be NULL return filename; }
static void RemoveDatafileCallback (TRI_datafile_t* datafile, void* data) { TRI_collection_t* collection; char* old; char* filename; char* name; char* number; bool ok; int res; collection = data; number = TRI_StringUInt32(datafile->_fid); name = TRI_Concatenate3String("deleted-", number, ".db"); filename = TRI_Concatenate2File(collection->_directory, name); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, name); old = datafile->_filename; ok = TRI_RenameDatafile(datafile, filename); if (! ok) { LOG_ERROR("cannot rename obsolete datafile '%s' to '%s': %s", old, filename, TRI_last_error()); } LOG_DEBUG("finished compactifing datafile '%s'", datafile->_filename); ok = TRI_CloseDatafile(datafile); if (! ok) { LOG_ERROR("cannot close obsolete datafile '%s': %s", datafile->_filename, TRI_last_error()); } else { if (collection->_vocbase->_removeOnCompacted) { LOG_DEBUG("wiping compacted datafile from disk"); res = TRI_UnlinkFile(filename); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("cannot wipe obsolete datafile '%s': %s", datafile->_filename, TRI_last_error()); } } } TRI_FreeDatafile(datafile); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); }
static void ScanPath (TRI_vocbase_t* vocbase, char const* path) { TRI_vector_string_t files; TRI_col_type_e type; size_t n; size_t i; files = TRI_FilesDirectory(path); n = files._length; for (i = 0; i < n; ++i) { char* name; char* file; name = files._buffer[i]; if (name[0] == '\0' || name[0] == '_' || name[0] == '.') { continue; } file = TRI_Concatenate2File(path, name); if (!file) { continue; } if (TRI_IsDirectory(file)) { TRI_col_info_t info; bool ok; ok = TRI_LoadParameterInfo(file, &info); if (! ok) { LOG_DEBUG("ignoring directory '%s' without valid parameter file '%s'", file, TRI_COL_PARAMETER_FILE); } else { type = info._type; if (type == TRI_COL_TYPE_SIMPLE_DOCUMENT) { AddCollection(vocbase, type, info._name, info._cid, file); LOG_DEBUG("added simple document collection from '%s'", file); } else { LOG_DEBUG("skipping collection of unknown type %d", (int) type); } } } else { LOG_DEBUG("ignoring non-directory '%s'", file); } TRI_FreeString(file); } TRI_DestroyVectorString(&files); }
int TRI_SaveCollectionInfo (char const* path, const TRI_col_info_t* const info) { TRI_json_t* json; char* filename; bool ok; filename = TRI_Concatenate2File(path, TRI_COL_PARAMETER_FILE); // create a json info object json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE); if (json == NULL) { // out of memory LOG_ERROR("cannot save info block '%s': out of memory", filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_OUT_OF_MEMORY; } TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "version", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_version)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "type", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_type)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "cid", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_cid)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "deleted", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, info->_deleted)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "maximalSize", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_maximalSize)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "name", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, info->_name)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "isVolatile", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, info->_isVolatile)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "waitForSync", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, info->_waitForSync)); if (info->_keyOptions) { TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "keyOptions", TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, info->_keyOptions)); } // save json info to file ok = TRI_SaveJson(filename, json); TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); if (! ok) { LOG_ERROR("cannot save info block '%s': '%s'", filename, TRI_last_error()); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_errno(); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_NO_ERROR; }
bool TRI_ExecuteRubyDirectory (mrb_state* mrb, char const* path) { TRI_vector_string_t files; bool result; regex_t re; size_t i; LOG_TRACE("loading ruby script directory: '%s'", path); files = TRI_FilesDirectory(path); regcomp(&re, "^(.*)\\.rb$", REG_ICASE | REG_EXTENDED); result = true; for (i = 0; i < files._length; ++i) { bool ok; char const* filename; char* full; filename = files._buffer[i]; if (! regexec(&re, filename, 0, 0, 0) == 0) { continue; } full = TRI_Concatenate2File(path, filename); ok = TRI_ExecuteRubyFile(mrb, full); TRI_FreeString(TRI_CORE_MEM_ZONE, full); result = result && ok; if (! ok) { TRI_LogRubyException(mrb, mrb->exc); } } TRI_DestroyVectorString(&files); regfree(&re); return result; }
int TRI_LoadCollectionInfo (char const* path, TRI_col_info_t* parameter) { TRI_json_t* json; char* filename; char* error = NULL; size_t i; size_t n; memset(parameter, 0, sizeof(TRI_col_info_t)); // find parameter file filename = TRI_Concatenate2File(path, TRI_COL_PARAMETER_FILE); if (filename == NULL) { LOG_ERROR("cannot load parameter info for collection '%s', out of memory", path); return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); } if (! TRI_ExistsFile(filename)) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } json = TRI_JsonFile(TRI_UNKNOWN_MEM_ZONE, filename, &error); if (json == NULL) { if (error != NULL) { LOG_ERROR("cannot open '%s', parameter block not readable: %s", filename, error); TRI_FreeString(TRI_CORE_MEM_ZONE, error); } else { LOG_ERROR("cannot open '%s', parameter block not readable", filename); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } if (json->_type != TRI_JSON_ARRAY) { LOG_ERROR("cannot open '%s', file does not contain a json array", filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); // convert json n = json->_value._objects._length; for (i = 0; i < n; i += 2) { TRI_json_t* key; TRI_json_t* value; key = TRI_AtVector(&json->_value._objects, i); value = TRI_AtVector(&json->_value._objects, i + 1); if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_NUMBER) { if (TRI_EqualString(key->_value._string.data, "version")) { parameter->_version = value->_value._number; } else if (TRI_EqualString(key->_value._string.data, "type")) { parameter->_type = value->_value._number; } else if (TRI_EqualString(key->_value._string.data, "cid")) { parameter->_cid = value->_value._number; } else if (TRI_EqualString(key->_value._string.data, "maximalSize")) { parameter->_maximalSize = value->_value._number; } } else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_STRING) { if (TRI_EqualString(key->_value._string.data, "name")) { TRI_CopyString(parameter->_name, value->_value._string.data, sizeof(parameter->_name)); parameter->_isSystem = TRI_IsSystemCollectionName(parameter->_name); } } else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_BOOLEAN) { if (TRI_EqualString(key->_value._string.data, "deleted")) { parameter->_deleted = value->_value._boolean; } else if (TRI_EqualString(key->_value._string.data, "isVolatile")) { parameter->_isVolatile = value->_value._boolean; } else if (TRI_EqualString(key->_value._string.data, "waitForSync")) { parameter->_waitForSync = value->_value._boolean; } } else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_ARRAY) { if (TRI_EqualString(key->_value._string.data, "keyOptions")) { parameter->_keyOptions = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, value); } } } TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); return TRI_ERROR_NO_ERROR; }
static char* GetConfigurationFilename (TRI_vocbase_t* vocbase) { return TRI_Concatenate2File(vocbase->_path, "REPLICATION-APPLIER-CONFIG"); }
static char* GetStateFilename (TRI_vocbase_t* vocbase) { return TRI_Concatenate2File(vocbase->_path, "REPLICATION-APPLIER-STATE"); }
static void DropDatafileCallback (TRI_datafile_t* datafile, void* data) { TRI_primary_collection_t* primary; TRI_voc_fid_t fid; char* filename; char* name; char* number; char* copy; bool ok; primary = data; fid = datafile->_fid; copy = NULL; number = TRI_StringUInt64(fid); name = TRI_Concatenate3String("deleted-", number, ".db"); filename = TRI_Concatenate2File(primary->base._directory, name); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, name); if (datafile->isPhysical(datafile)) { copy = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, datafile->_filename); ok = TRI_RenameDatafile(datafile, filename); if (! ok) { LOG_ERROR("cannot rename obsolete datafile '%s' to '%s': %s", copy, filename, TRI_last_error()); } } LOG_DEBUG("finished compacting datafile '%s'", datafile->getName(datafile)); ok = TRI_CloseDatafile(datafile); if (! ok) { LOG_ERROR("cannot close obsolete datafile '%s': %s", datafile->getName(datafile), TRI_last_error()); } else if (datafile->isPhysical(datafile)) { if (primary->base._vocbase->_settings.removeOnCompacted) { int res; LOG_DEBUG("wiping compacted datafile from disk"); res = TRI_UnlinkFile(filename); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("cannot wipe obsolete datafile '%s': %s", datafile->getName(datafile), TRI_last_error()); } // check for .dead files if (copy != NULL) { // remove .dead file for datafile char* deadfile = TRI_Concatenate2String(copy, ".dead"); if (deadfile != NULL) { // check if .dead file exists, then remove it if (TRI_ExistsFile(deadfile)) { TRI_UnlinkFile(deadfile); } TRI_FreeString(TRI_CORE_MEM_ZONE, deadfile); } } } } TRI_FreeDatafile(datafile); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); if (copy != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, copy); } }
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); }
int TRI_ZipFile (const char* filename, const char* dir, TRI_vector_string_t const* files, const char* password) { void* buffer; size_t bufferSize; zipFile zf; #ifdef USEWIN32IOAPI zlib_filefunc64_def ffunc; #endif size_t i, n; int res; if (TRI_ExistsFile(filename)) { return TRI_ERROR_CANNOT_OVERWRITE_FILE; } bufferSize = 16384; buffer = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, bufferSize, false); if (buffer == NULL) { return TRI_ERROR_OUT_OF_MEMORY; } #ifdef USEWIN32IOAPI fill_win32_filefunc64A(&ffunc); zf = zipOpen2_64(filename, 0, NULL, &ffunc); #else zf = zipOpen64(filename, 0); #endif if (zf == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, buffer); return ZIP_ERRNO; } res = TRI_ERROR_NO_ERROR; n = files->_length; for (i = 0; i < n; ++i) { FILE* fin; char* file; char* fullfile; char* saveName; zip_fileinfo zi; uint32_t crc; int isLarge; file = TRI_AtVectorString(files, i); if (*dir == '\0') { fullfile = TRI_DuplicateString(file); } else { fullfile = TRI_Concatenate2File(dir, file); } memset(&zi, 0, sizeof(zi)); res = TRI_Crc32File(fullfile, &crc); if (res != TRI_ERROR_NO_ERROR) { break; } isLarge = (TRI_SizeFile(file) > 0xFFFFFFFFLL); saveName = file; while (*saveName == '\\' || *saveName == '/') { ++saveName; } if (zipOpenNewFileInZip3_64(zf, saveName, &zi, NULL, 0, NULL, 0, NULL, /* comment*/ Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, password, (unsigned long) crc, isLarge) != ZIP_OK) { } fin = fopen(fullfile, "rb"); TRI_FreeString(TRI_CORE_MEM_ZONE, fullfile); if (fin == NULL) { break; } while (true) { int sizeRead; sizeRead = (int) fread(buffer, 1, bufferSize, fin); if (sizeRead < bufferSize) { if (feof(fin) == 0) { res = TRI_set_errno(TRI_ERROR_SYS_ERROR); break; } } if (sizeRead > 0) { res = zipWriteInFileInZip(zf, buffer, sizeRead); if (res != 0) { break; } } else if (sizeRead <= 0) { break; } } fclose(fin); zipCloseFileInZip(zf); if (res != TRI_ERROR_NO_ERROR) { break; } } zipClose(zf, NULL); TRI_Free(TRI_UNKNOWN_MEM_ZONE, buffer); return res; }
static int ExtractCurrentFile (unzFile uf, void* buffer, const size_t bufferSize, const char* outPath, const bool skipPaths, const bool overwrite, const char* password) { char filenameInZip[256]; char* filenameWithoutPath; char* fullPath; char* p; FILE *fout; unz_file_info64 fileInfo; if (unzGetCurrentFileInfo64(uf, &fileInfo, filenameInZip, sizeof(filenameInZip), NULL, 0, NULL, 0) != UNZ_OK) { return TRI_ERROR_INTERNAL; } p = filenameWithoutPath = filenameInZip; // get the file name without any path prefix while (*p != '\0') { if (*p == '/' || *p == '\\') { filenameWithoutPath = p + 1; } p++; } // found a directory if (*filenameWithoutPath == '\0') { if (! skipPaths) { fullPath = TRI_Concatenate2File(outPath, filenameInZip); TRI_CreateRecursiveDirectory(fullPath); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); } } // found a file else { const char* writeFilename; if (! skipPaths) { writeFilename = filenameInZip; } else { writeFilename = filenameWithoutPath; } if (unzOpenCurrentFilePassword(uf, password) != UNZ_OK) { return TRI_ERROR_INTERNAL; } // prefix the name from the zip file with the path specified fullPath = TRI_Concatenate2File(outPath, writeFilename); if (! overwrite && TRI_ExistsFile(fullPath)) { return TRI_ERROR_INTERNAL; } // try to write the outfile fout = fopen(fullPath, "wb"); // cannot write to outfile. this may be due to the target directory missing if (fout == NULL && ! skipPaths && filenameWithoutPath != (char*) filenameInZip) { char* d; char c = *(filenameWithoutPath - 1); *(filenameWithoutPath - 1) = '\0'; // create target directory recursively d = TRI_Concatenate2File(outPath, filenameInZip); TRI_CreateRecursiveDirectory(d); TRI_Free(TRI_CORE_MEM_ZONE, d); *(filenameWithoutPath - 1) = c; // try again fout = fopen(fullPath, "wb"); } TRI_Free(TRI_CORE_MEM_ZONE, fullPath); if (fout == NULL) { return TRI_ERROR_CANNOT_WRITE_FILE; } while (true) { int result = unzReadCurrentFile(uf, buffer, bufferSize); if (result < 0) { fclose(fout); return TRI_ERROR_INTERNAL; } if (result > 0) { if (fwrite(buffer, result, 1, fout) != 1) { fclose(fout); return TRI_set_errno(TRI_ERROR_SYS_ERROR); } } else { assert(result == 0); break; } } fclose(fout); } unzCloseCurrentFile(uf); return TRI_ERROR_NO_ERROR; }
static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize, char const* outPath, bool const skipPaths, bool const overwrite, char const* password, std::string& errorMessage) { char filenameInZip[256]; char* filenameWithoutPath; char* fullPath; char* p; unz_file_info64 fileInfo; long systemError; int err; // cppcheck-suppress * FILE* fout; filenameInZip[0] = '\0'; err = unzGetCurrentFileInfo64(uf, &fileInfo, filenameInZip, sizeof(filenameInZip), NULL, 0, NULL, 0); if (err != UNZ_OK) { errorMessage = std::string("Failed to get file info for ") + filenameInZip + ": " + std::to_string(err); return TRI_ERROR_INTERNAL; } // adjust file name p = filenameInZip; while (*p != '\0') { #ifdef WIN32 if (*p == '/') { *p = '\\'; } #else if (*p == '\\') { *p = '/'; } #endif ++p; } p = filenameWithoutPath = filenameInZip; // get the file name without any path prefix while (*p != '\0') { if (*p == '/' || *p == '\\' || *p == ':') { filenameWithoutPath = p + 1; } p++; } // found a directory if (*filenameWithoutPath == '\0') { if (!skipPaths) { fullPath = TRI_Concatenate2File(outPath, filenameInZip); int res = TRI_CreateRecursiveDirectory(fullPath, systemError, errorMessage); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_CORE_MEM_ZONE, fullPath); return res; } TRI_Free(TRI_CORE_MEM_ZONE, fullPath); } } // found a file else { char const* writeFilename; if (!skipPaths) { writeFilename = filenameInZip; } else { writeFilename = filenameWithoutPath; } err = unzOpenCurrentFilePassword(uf, password); if (err != UNZ_OK) { errorMessage = "failed to authenticate the password in the zip: " + std::to_string(err); return TRI_ERROR_INTERNAL; } // prefix the name from the zip file with the path specified fullPath = TRI_Concatenate2File(outPath, writeFilename); if (!overwrite && TRI_ExistsFile(fullPath)) { TRI_Free(TRI_CORE_MEM_ZONE, fullPath); errorMessage = std::string("not allowed to overwrite file ") + fullPath; return TRI_ERROR_CANNOT_OVERWRITE_FILE; } // try to write the outfile fout = fopen(fullPath, "wb"); // cannot write to outfile. this may be due to the target directory missing if (fout == nullptr && !skipPaths && filenameWithoutPath != (char*)filenameInZip) { char c = *(filenameWithoutPath - 1); *(filenameWithoutPath - 1) = '\0'; // create target directory recursively char* d = TRI_Concatenate2File(outPath, filenameInZip); int res = TRI_CreateRecursiveDirectory(d, systemError, errorMessage); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_CORE_MEM_ZONE, d); return res; } TRI_Free(TRI_CORE_MEM_ZONE, d); *(filenameWithoutPath - 1) = c; // try again fout = fopen(fullPath, "wb"); } else if (fout == nullptr) { // try to create the target directory recursively char* d = TRI_Concatenate2File(outPath, filenameInZip); // strip filename so we only have the directory name char* dir = TRI_Dirname(d); int res = TRI_CreateRecursiveDirectory(dir, systemError, errorMessage); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_CORE_MEM_ZONE, d); TRI_Free(TRI_CORE_MEM_ZONE, dir); return res; } TRI_Free(TRI_CORE_MEM_ZONE, d); TRI_Free(TRI_CORE_MEM_ZONE, dir); // try again fout = fopen(fullPath, "wb"); } if (fout == NULL) { errorMessage = std::string("failed to open file for writing: ") + fullPath + " - " + strerror(errno); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); return TRI_ERROR_CANNOT_WRITE_FILE; } while (true) { int result = unzReadCurrentFile(uf, buffer, (unsigned int)bufferSize); if (result < 0) { errorMessage = std::string("failed to write file ") + fullPath + " - " + strerror(errno); fclose(fout); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); return TRI_ERROR_CANNOT_WRITE_FILE; } if (result > 0) { if (fwrite(buffer, result, 1, fout) != 1) { errorMessage = std::string("failed to write file ") + fullPath + " - " + strerror(errno); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); fclose(fout); return TRI_set_errno(TRI_ERROR_SYS_ERROR); } } else { TRI_ASSERT(result == 0); break; } } TRI_Free(TRI_CORE_MEM_ZONE, fullPath); fclose(fout); } unzCloseCurrentFile(uf); return TRI_ERROR_NO_ERROR; }
static bool CreateJournal (TRI_shape_collection_t* collection) { TRI_col_header_marker_t cm; TRI_datafile_t* journal; TRI_df_marker_t* position; char* filename; int res; if (collection->base._info._isVolatile) { // in memory collection filename = NULL; } else { char* jname; char* number; number = TRI_StringUInt32(TRI_NewTickVocBase()); if (! number) { return false; } jname = TRI_Concatenate3String("journal-", number, ".db"); TRI_FreeString(TRI_CORE_MEM_ZONE, number); filename = TRI_Concatenate2File(collection->base._directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); } journal = TRI_CreateDatafile(filename, collection->base._info._maximalSize); if (filename != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } // check that a journal was created if (journal == NULL) { if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) { collection->base._lastError = TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY_MMAP); collection->base._state = TRI_COL_STATE_READ; } else { collection->base._lastError = TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); collection->base._state = TRI_COL_STATE_WRITE_ERROR; } return false; } LOG_TRACE("created a new shape journal '%s'", journal->getName(journal)); if (journal->isPhysical(journal)) { char* jname; char* number; bool ok; // and use the correct name number = TRI_StringUInt32(journal->_fid); jname = TRI_Concatenate3String("journal-", number, ".db"); filename = TRI_Concatenate2File(collection->base._directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); ok = TRI_RenameDatafile(journal, filename); if (! ok) { // TODO: remove disastrous call to exit() here LOG_FATAL_AND_EXIT("failed to rename the journal to '%s': %s", filename, TRI_last_error()); } else { LOG_TRACE("renamed journal to '%s'", filename); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } // create a collection header res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("cannot create document header in journal '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return false; } // create a header memset(&cm, 0, sizeof(cm)); cm.base._size = sizeof(TRI_col_header_marker_t); cm.base._type = TRI_COL_MARKER_HEADER; cm.base._tick = TRI_NewTickVocBase(); cm._cid = collection->base._info._cid; TRI_FillCrcMarkerDatafile(journal, &cm.base, sizeof(cm), 0, 0, 0, 0); // on journal creation, always use waitForSync = true res = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, 0, 0, true); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("cannot create document header in journal '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return false; } // that's it TRI_PushBackVectorPointer(&collection->base._journals, journal); return true; }
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; }
static TRI_col_file_structure_t ScanCollectionDirectory (char const* path) { TRI_col_file_structure_t structure; TRI_vector_string_t files; regex_t re; size_t i; size_t n; // check files within the directory files = TRI_FilesDirectory(path); n = files._length; regcomp(&re, "^(journal|datafile|index|compactor)-([0-9][0-9]*)\\.(db|json)$", REG_EXTENDED); TRI_InitVectorString(&structure._journals, TRI_CORE_MEM_ZONE); TRI_InitVectorString(&structure._compactors, TRI_CORE_MEM_ZONE); TRI_InitVectorString(&structure._datafiles, TRI_CORE_MEM_ZONE); TRI_InitVectorString(&structure._indexes, TRI_CORE_MEM_ZONE); for (i = 0; i < n; ++i) { char const* file = files._buffer[i]; regmatch_t matches[4]; if (regexec(&re, file, sizeof(matches) / sizeof(matches[0]), matches, 0) == 0) { char const* first = file + matches[1].rm_so; size_t firstLen = matches[1].rm_eo - matches[1].rm_so; char const* third = file + matches[3].rm_so; size_t thirdLen = matches[3].rm_eo - matches[3].rm_so; // ............................................................................. // file is an index // ............................................................................. if (TRI_EqualString2("index", first, firstLen) && TRI_EqualString2("json", third, thirdLen)) { char* filename; filename = TRI_Concatenate2File(path, file); TRI_PushBackVectorString(&structure._indexes, filename); } // ............................................................................. // file is a journal or datafile // ............................................................................. else if (TRI_EqualString2("db", third, thirdLen)) { char* filename; filename = TRI_Concatenate2File(path, file); // file is a journal if (TRI_EqualString2("journal", first, firstLen)) { TRI_PushBackVectorString(&structure._journals, filename); } // file is a compactor file else if (TRI_EqualString2("compactor", first, firstLen)) { TRI_PushBackVectorString(&structure._compactors, filename); } // file is a datafile else if (TRI_EqualString2("datafile", first, firstLen)) { TRI_PushBackVectorString(&structure._datafiles, filename); } // ups, what kind of file is that else { LOG_ERROR("unknown datafile '%s'", file); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } } else { LOG_ERROR("unknown datafile '%s'", file); } } } TRI_DestroyVectorString(&files); regfree(&re); return structure; }
static TRI_datafile_t* CreateCompactor (TRI_primary_collection_t* primary, TRI_voc_fid_t fid, TRI_voc_size_t maximalSize) { TRI_col_header_marker_t cm; TRI_collection_t* collection; TRI_datafile_t* journal; TRI_df_marker_t* position; int res; collection = &primary->base; if (collection->_info._isVolatile) { // in-memory collection journal = TRI_CreateDatafile(NULL, fid, maximalSize); } else { char* jname; char* number; char* filename; number = TRI_StringUInt64(fid); jname = TRI_Concatenate3String("compaction-", number, ".db"); filename = TRI_Concatenate2File(collection->_directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); if (TRI_ExistsFile(filename)) { // remove any existing temporary file first TRI_UnlinkFile(filename); } journal = TRI_CreateDatafile(filename, fid, maximalSize); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } if (journal == NULL) { if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) { collection->_lastError = TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY_MMAP); collection->_state = TRI_COL_STATE_READ; } else { collection->_lastError = TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); collection->_state = TRI_COL_STATE_WRITE_ERROR; } return NULL; } LOG_TRACE("created new compactor '%s'", journal->getName(journal)); // create a collection header, still in the temporary file res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position, maximalSize); if (res != TRI_ERROR_NO_ERROR) { collection->_lastError = journal->_lastError; LOG_ERROR("cannot create document header in compactor '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return NULL; } TRI_InitMarker((char*) &cm, TRI_COL_MARKER_HEADER, sizeof(TRI_col_header_marker_t)); cm.base._tick = (TRI_voc_tick_t) fid; cm._type = (TRI_col_type_t) collection->_info._type; cm._cid = collection->_info._cid; res = TRI_WriteCrcElementDatafile(journal, position, &cm.base, sizeof(cm), false); if (res != TRI_ERROR_NO_ERROR) { collection->_lastError = journal->_lastError; LOG_ERROR("cannot create document header in compactor '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return NULL; } assert(fid == journal->_fid); return journal; }
static bool CheckCollection (TRI_collection_t* collection) { TRI_datafile_t* datafile; TRI_vector_pointer_t all; TRI_vector_pointer_t compactors; TRI_vector_pointer_t datafiles; TRI_vector_pointer_t journals; TRI_vector_pointer_t sealed; TRI_vector_string_t files; bool stop; regex_t re; size_t i; size_t n; stop = false; // check files within the directory files = TRI_FilesDirectory(collection->_directory); n = files._length; regcomp(&re, "^(journal|datafile|index|compactor)-([0-9][0-9]*)\\.(db|json)$", REG_EXTENDED); TRI_InitVectorPointer(&journals, TRI_UNKNOWN_MEM_ZONE); TRI_InitVectorPointer(&compactors, TRI_UNKNOWN_MEM_ZONE); TRI_InitVectorPointer(&datafiles, TRI_UNKNOWN_MEM_ZONE); TRI_InitVectorPointer(&sealed, TRI_UNKNOWN_MEM_ZONE); TRI_InitVectorPointer(&all, TRI_UNKNOWN_MEM_ZONE); for (i = 0; i < n; ++i) { char const* file = files._buffer[i]; regmatch_t matches[4]; if (regexec(&re, file, sizeof(matches) / sizeof(matches[0]), matches, 0) == 0) { char const* first = file + matches[1].rm_so; size_t firstLen = matches[1].rm_eo - matches[1].rm_so; char const* third = file + matches[3].rm_so; size_t thirdLen = matches[3].rm_eo - matches[3].rm_so; // ............................................................................. // file is an index, just store the filename // ............................................................................. if (TRI_EqualString2("index", first, firstLen) && TRI_EqualString2("json", third, thirdLen)) { char* filename; filename = TRI_Concatenate2File(collection->_directory, file); TRI_PushBackVectorString(&collection->_indexFiles, filename); } // ............................................................................. // file is a journal or datafile, open the datafile // ............................................................................. else if (TRI_EqualString2("db", third, thirdLen)) { char* filename; char* ptr; TRI_col_header_marker_t* cm; filename = TRI_Concatenate2File(collection->_directory, file); datafile = TRI_OpenDatafile(filename); if (datafile == NULL) { collection->_lastError = TRI_errno(); stop = true; LOG_ERROR("cannot open datafile '%s': %s", filename, TRI_last_error()); break; } TRI_PushBackVectorPointer(&all, datafile); // check the document header ptr = datafile->_data; ptr += TRI_DF_ALIGN_BLOCK(sizeof(TRI_df_header_marker_t)); cm = (TRI_col_header_marker_t*) ptr; if (cm->base._type != TRI_COL_MARKER_HEADER) { LOG_ERROR("collection header mismatch in file '%s', expected TRI_COL_MARKER_HEADER, found %lu", filename, (unsigned long) cm->base._type); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); stop = true; break; } if (cm->_cid != collection->_info._cid) { LOG_ERROR("collection identifier mismatch, expected %llu, found %llu", (unsigned long long) collection->_info._cid, (unsigned long long) cm->_cid); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); stop = true; break; } // file is a journal if (TRI_EqualString2("journal", first, firstLen)) { if (datafile->_isSealed) { LOG_WARNING("strange, journal '%s' is already sealed; must be a left over; will use it as datafile", filename); TRI_PushBackVectorPointer(&sealed, datafile); } else { TRI_PushBackVectorPointer(&journals, datafile); } } // file is a compactor file else if (TRI_EqualString2("compactor", first, firstLen)) { if (datafile->_isSealed) { LOG_WARNING("strange, compactor journal '%s' is already sealed; must be a left over; will use it as datafile", filename); TRI_PushBackVectorPointer(&sealed, datafile); } else { TRI_PushBackVectorPointer(&compactors, datafile); } } // file is a datafile else if (TRI_EqualString2("datafile", first, firstLen)) { if (! datafile->_isSealed) { LOG_ERROR("datafile '%s' is not sealed, this should never happen", filename); collection->_lastError = TRI_set_errno(TRI_ERROR_ARANGO_CORRUPTED_DATAFILE); stop = true; break; } else { TRI_PushBackVectorPointer(&datafiles, datafile); } } else { LOG_ERROR("unknown datafile '%s'", file); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } else { LOG_ERROR("unknown datafile '%s'", file); } } } TRI_DestroyVectorString(&files); regfree(&re); // convert the sealed journals into datafiles if (! stop) { n = sealed._length; for (i = 0; i < n; ++i) { char* number; char* dname; char* filename; bool ok; datafile = sealed._buffer[i]; number = TRI_StringUInt64(datafile->_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(datafile, filename); if (ok) { TRI_PushBackVectorPointer(&datafiles, datafile); LOG_DEBUG("renamed sealed journal to '%s'", filename); } else { collection->_lastError = datafile->_lastError; stop = true; LOG_ERROR("cannot rename sealed log-file to %s, this should not happen: %s", filename, TRI_last_error()); break; } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } } TRI_DestroyVectorPointer(&sealed); // stop if necessary if (stop) { n = all._length; for (i = 0; i < n; ++i) { datafile = all._buffer[i]; LOG_TRACE("closing datafile '%s'", datafile->_filename); TRI_CloseDatafile(datafile); TRI_FreeDatafile(datafile); } TRI_DestroyVectorPointer(&all); TRI_DestroyVectorPointer(&datafiles); return false; } TRI_DestroyVectorPointer(&all); // add the datafiles and journals collection->_datafiles = datafiles; collection->_journals = journals; collection->_compactors = compactors; return true; }
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; }
static TRI_datafile_t* CreateJournal (TRI_primary_collection_t* primary, bool compactor) { TRI_col_header_marker_t cm; TRI_collection_t* collection; TRI_datafile_t* journal; TRI_df_marker_t* position; int res; char* filename; collection = &primary->base; if (collection->_info._isVolatile) { // in-memory collection filename = NULL; } else { char* jname; char* number; // construct a suitable filename number = TRI_StringUInt64(TRI_NewTickVocBase()); if (compactor) { jname = TRI_Concatenate3String("journal-", number, ".db"); } else { jname = TRI_Concatenate3String("compactor-", number, ".db"); } filename = TRI_Concatenate2File(collection->_directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); } // create journal file journal = TRI_CreateDatafile(filename, collection->_info._maximalSize); if (filename != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } if (journal == NULL) { if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) { collection->_lastError = TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY_MMAP); collection->_state = TRI_COL_STATE_READ; } else { collection->_lastError = TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); collection->_state = TRI_COL_STATE_WRITE_ERROR; } return NULL; } LOG_TRACE("created a new primary journal '%s'", journal->getName(journal)); if (journal->isPhysical(journal)) { char* jname; char* number; bool ok; // and use the correct name number = TRI_StringUInt64(journal->_fid); if (compactor) { jname = TRI_Concatenate3String("compactor-", number, ".db"); } else { jname = TRI_Concatenate3String("journal-", number, ".db"); } filename = TRI_Concatenate2File(collection->_directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); ok = TRI_RenameDatafile(journal, filename); if (! ok) { LOG_WARNING("failed to rename the journal to '%s': %s", filename, TRI_last_error()); } else { LOG_TRACE("renamed journal to '%s'", filename); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } // create a collection header res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position); if (res != TRI_ERROR_NO_ERROR) { collection->_lastError = journal->_lastError; LOG_ERROR("cannot create document header in journal '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return NULL; } memset(&cm, 0, sizeof(cm)); cm.base._size = sizeof(TRI_col_header_marker_t); cm.base._type = TRI_COL_MARKER_HEADER; cm.base._tick = TRI_NewTickVocBase(); cm._cid = collection->_info._cid; TRI_FillCrcMarkerDatafile(journal, &cm.base, sizeof(cm), 0, 0, 0, 0); res = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, 0, 0, true); if (res != TRI_ERROR_NO_ERROR) { collection->_lastError = journal->_lastError; LOG_ERROR("cannot create document header in journal '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return NULL; } // that's it if (compactor) { TRI_PushBackVectorPointer(&collection->_compactors, journal); } else { TRI_PushBackVectorPointer(&collection->_journals, journal); } return journal; }
static TRI_datafile_t* CreateJournal (TRI_primary_collection_t* primary, TRI_voc_size_t maximalSize) { TRI_col_header_marker_t cm; TRI_collection_t* collection; TRI_datafile_t* journal; TRI_df_marker_t* position; TRI_voc_fid_t fid; int res; collection = &primary->base; fid = (TRI_voc_fid_t) TRI_NewTickServer(); if (collection->_info._isVolatile) { // in-memory collection journal = TRI_CreateDatafile(NULL, fid, maximalSize); } else { char* jname; char* number; char* filename; // construct a suitable filename (which is temporary at the beginning) number = TRI_StringUInt64(fid); jname = TRI_Concatenate3String("temp-", number, ".db"); filename = TRI_Concatenate2File(collection->_directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); journal = TRI_CreateDatafile(filename, fid, maximalSize); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } if (journal == NULL) { if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) { collection->_lastError = TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY_MMAP); collection->_state = TRI_COL_STATE_READ; } else { collection->_lastError = TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); collection->_state = TRI_COL_STATE_WRITE_ERROR; } return NULL; } LOG_TRACE("created new journal '%s'", journal->getName(journal)); // create a collection header, still in the temporary file res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position, maximalSize); if (res != TRI_ERROR_NO_ERROR) { collection->_lastError = journal->_lastError; LOG_ERROR("cannot create document header in journal '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return NULL; } TRI_InitMarker((char*) &cm, TRI_COL_MARKER_HEADER, sizeof(TRI_col_header_marker_t)); cm.base._tick = (TRI_voc_tick_t) fid; cm._type = (TRI_col_type_t) collection->_info._type; cm._cid = collection->_info._cid; res = TRI_WriteCrcElementDatafile(journal, position, &cm.base, sizeof(cm), true); if (res != TRI_ERROR_NO_ERROR) { collection->_lastError = journal->_lastError; LOG_ERROR("cannot create document header in journal '%s': %s", journal->getName(journal), TRI_last_error()); TRI_FreeDatafile(journal); return NULL; } assert(fid == journal->_fid); // if a physical file, we can rename it from the temporary name to the correct name if (journal->isPhysical(journal)) { char* jname; char* number; char* filename; bool ok; // and use the correct name number = TRI_StringUInt64(journal->_fid); jname = TRI_Concatenate3String("journal-", number, ".db"); filename = TRI_Concatenate2File(collection->_directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); ok = TRI_RenameDatafile(journal, filename); if (! ok) { LOG_ERROR("failed to rename the journal to '%s': %s", filename, TRI_last_error()); TRI_FreeDatafile(journal); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return NULL; } else { LOG_TRACE("renamed journal from %s to '%s'", journal->getName(journal), filename); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } TRI_PushBackVectorPointer(&collection->_journals, journal); return journal; }