示例#1
0
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;
}
示例#2
0
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);
}
示例#3
0
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);
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
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;
}
示例#7
0
static char* GetConfigurationFilename (TRI_vocbase_t* vocbase) {
  return TRI_Concatenate2File(vocbase->_path, "REPLICATION-APPLIER-CONFIG");
}
示例#8
0
static char* GetStateFilename (TRI_vocbase_t* vocbase) {
  return TRI_Concatenate2File(vocbase->_path, "REPLICATION-APPLIER-STATE");
}
示例#9
0
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);
  }
}
示例#10
0
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);
}
示例#11
0
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;
}
示例#12
0
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;
}
示例#13
0
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;
}
示例#14
0
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;
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
0
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;
}
示例#18
0
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;
}
示例#19
0
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;
}
示例#20
0
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;
}
示例#21
0
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;
}