/** Release an open file
 *
 * Release is called when there are no more references to an open
 * file: all file descriptors are closed and all memory mappings
 * are unmapped.
 *
 * For every open() call there will be exactly one release() call
 * with the same flags and file descriptor.  It is possible to
 * have a file opened more than once, in which case only the last
 * release will mean, that no more reads/writes will happen on the
 * file.  The return value of release is ignored.
 *
 * Changed in version 2.2
 */
int cloudfs_release(const char *path, struct fuse_file_info *fi)
{
  static int count;
  char new_name[MAX_NAME_LENGTH];
  char symlink_name[MAX_NAME_LENGTH];
  char buf[MAX_BUFFER_SIZE];
  char fpath[PATH_MAX];
  char symlink_path[PATH_MAX];
  char file_to_link[PATH_MAX];
  char new_hdd_path[PATH_MAX];
  char attr_file_name[PATH_MAX];
  char temp[PATH_MAX];
  int retstat = 0;
  int fd;
  int temp_fd;
  int n;
  struct stat file_attributes; 

  d_printf("\ncloudfs_release(path=\"%s\", fi=0x%08x)\n",  path, fi);
  //    log_fi(fi);


  //Read file attributes to get size of file
  fstat(fi->fh,&file_attributes);
  d_printf("Size of file is %d\n",file_attributes.st_size);

  //Open given file
  cloudfs_fullpath(fpath,path);
  if ((temp_fd = open(fpath,O_RDONLY)) < 0 )
    cloudfs_error("Problem opening original file\n");
  //Check if file is greater than threshold . 
  //If yes then write the file to hdd with name large<static counter>
  //Delete the original file from ssd and create a symlink to new file
  //in hdd  
  if (file_attributes.st_size > state_.threshold) {

    strcpy(new_hdd_path,path);
    get_new_name(new_hdd_path); //File's new name in HDD will have * instead of /
    strcpy(fpath, state_.hdd_path);
    strncat(fpath,new_hdd_path, PATH_MAX); 
    strncpy(file_to_link,fpath,PATH_MAX); //Full name of new file is what 
    //our symlink will point to
    fd = open(fpath,O_CREAT|O_RDWR,FILE_MODE);  //Getting new fd of file
    if (fd < 0){ 
      d_printf("Failed to open %s\n",fpath);
      retstat = cloudfs_error("cloudfs_create create error in HDD");
    }

    while ( (n = read(temp_fd,buf,4096))> 0 ) {
      write(fd,buf,n);              
    }

    //Close new file made
    close(fd);        

    //Create hidden attribute file  
    get_hidden_file_name(path,temp);
    strcpy(attr_file_name,temp);
    cloudfs_fullpath(fpath,path);
    append_to_end(fpath,attr_file_name);
    fd = open(fpath,O_CREAT|O_RDWR,FILE_MODE);  //Getting fd of hidden file
    d_printf("Making hidden file %s\n",fpath);
    if (fd < 0){ 
      d_printf("Failed to open %s\n",fpath);
      retstat = cloudfs_error("cloudfs_create create error of hidden attribute file");
    }   
    //Store attributes of migrated file in 
    //extended attributes of hidden attribute file
    set_extended_attributes(fpath,&file_attributes);


    close(fd);  //Close fd of hidden attribute file


    //Closing fd of original file and deleting
    //from SSD  
    if ((retstat = close(temp_fd)) < 0)
      cloudfs_error("Error closing original file\n");
    if ((retstat = close(fi->fh)) < 0)
      cloudfs_error("Error closing original file\n");

    cloudfs_fullpath(fpath,path);
    d_printf("Trying to delete file %s\n",fpath);
    if( remove(fpath) < 0 )
      cloudfs_error("Can't remove the file \n");


    //Creating symlink
    cloudfs_fullpath(fpath,path);
    strcpy(symlink_name,fpath);
    fd = symlink(file_to_link,fpath);  //Getting new fd of file
    if (fd < 0){ 
      d_printf("Failed to make symlink %s\n",fpath);
    }  


    return retstat;

  }
  // We need to close the file.  Had we allocated any resources
  // (buffers etc) we'd need to free them here as well.
  else {
    if ((retstat = close(temp_fd)) < 0)
      cloudfs_error("Error closing original file\n");
    if ((retstat = close(fi->fh)) < 0)
      cloudfs_error("Error closing original file\n");
    return retstat;
  }


}
Exemple #2
0
static int
get_insert_run_id(
        struct rldb_plugin_cnts *cdata,
        time_t t,
        int uid,
        int nsec)
{
  struct rldb_file_cnts *cs = (struct rldb_file_cnts*) cdata;
  struct runlog_state *rls = cs->rl_state;

  int i, j;
  struct run_entry *runs = 0;

  ASSERT(rls->run_u <= rls->run_a);
  if (rls->run_u == rls->run_a) {
    int new_a = rls->run_a * 2;
    struct run_entry *new_r = 0;

    if (!new_a) new_a = 128;
    XCALLOC(new_r, new_a);
    for (i = 0; i < new_a; ++i)
      new_r[i].status = RUN_EMPTY;
    if (rls->run_u > 0)
      memcpy(new_r, rls->runs, rls->run_u * sizeof(rls->runs[0]));
    xfree(rls->runs);
    rls->runs = new_r;
    rls->run_a = new_a;
  }
  runs = rls->runs;

  /*
   * RUN_EMPTY compilicates things! :(
   */
  if (!rls->run_u) return append_to_end(rls, t, nsec);

  j = rls->run_u - 1;
  while (j >= 0 && runs[j].status == RUN_EMPTY) j--;
  if (j < 0) return append_to_end(rls, t, nsec);
  if (t > runs[j].time) return append_to_end(rls, t, nsec);
  if (t == runs[j].time) {
    if (nsec < 0 && runs[j].nsec < NSEC_MAX) {
      nsec = runs[j].nsec + 1;
      return append_to_end(rls, t, nsec);
    }
    if (nsec > runs[j].nsec) return append_to_end(rls, t, nsec);
    if (nsec == runs[j].nsec && uid >= runs[j].user_id)
      return append_to_end(rls, t, nsec);
  }

  if (nsec < 0) {
    for (i = 0; i < rls->run_u; i++) {
      if (runs[i].status == RUN_EMPTY) continue;
      if (runs[i].time > t) break;
      if (runs[i].time < t) continue;
      // runs[i].time == t
      while (runs[i].status == RUN_EMPTY || runs[i].time == t) i++;
      j = i - 1;
      while (runs[j].status == RUN_EMPTY) j--;
      if (runs[j].nsec < NSEC_MAX) {
        nsec = runs[j].nsec + 1;
        break;
      }
      // DUMB :(
      nsec = random_u32() % (NSEC_MAX + 1);
      goto try_with_nsec;
    }
    ASSERT(i < rls->run_u);
  } else {
  try_with_nsec:
    for (i = 0; i < rls->run_u; i++) {
      if (runs[i].status == RUN_EMPTY) continue;
      if (runs[i].time > t) break;
      if (runs[i].time < t) continue;
      if (runs[i].nsec > nsec) break;
      if (runs[i].nsec < nsec) continue;
      if (runs[i].user_id > uid) break;
    }
  }

  /* So we going to insert a run at position i.
   * Check, that there is no "transient"-statused runs after this position.
   * This is very unlikely, because such runs appears when the run
   * is being compiled or run, and in this case its precise (nanosecond)
   * timestamp should be less, than the current run. However, if such
   * sutuation is detected, we fail because we cannot safely change
   * the run_id's when it is possible to receive compile or run response
   * packets.
   */
  for (j = i; j < rls->run_u; j++)
    if (runs[j].status >= RUN_TRANSIENT_FIRST
        && runs[j].status <= RUN_TRANSIENT_LAST)
      break;
  if (j < rls->run_u) {
    err("append_record: cannot safely insert a run at position %d", i);
    err("append_record: the run %d is transient!", j);
    return -1;
  }

  memmove(&runs[i + 1], &runs[i], (rls->run_u - i) * sizeof(runs[0]));
  rls->run_u++;
  for (j = i + 1; j < rls->run_u; j++)
    runs[j].run_id = j;

  if (nsec < 0) nsec = 0;
  memset(&runs[i], 0, sizeof(runs[0]));
  runs[i].run_id = i;
  runs[i].status = RUN_EMPTY;
  runs[i].time = t;
  runs[i].nsec = nsec;
  if (sf_lseek(cs->run_fd, sizeof(rls->head) + i * sizeof(runs[0]),
               SEEK_SET, "run") == (off_t) -1) return -1;
  if (do_write(cs->run_fd, &runs[i], (rls->run_u - i) * sizeof(runs[0])) < 0)
    return -1;
  return i;
}