⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ondemand.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
      {
        GNUNET_free (dsvalue);
      }
  }
#endif
  return datastore->putUpdate (&key, &odb.header);
}

/**
 * Call datastore's delete method using the
 * query and datastore value from the closure.
 * (and free the closure).
 */
static void
async_delete_job (void *cls)
{
  GNUNET_HashCode *query = cls;
  GNUNET_DatastoreValue *dbv = (GNUNET_DatastoreValue *) & query[1];

  datastore->del (query, dbv);
  GNUNET_free (query);
}

/**
 * Delete the query that still references the unavailable file.  This
 * must be done asynchronously since we are in the "get" iterator and
 * a del operation during "get" would deadlock!
 */
static void
delete_content_asynchronously (const GNUNET_DatastoreValue * dbv,
                               const GNUNET_HashCode * query)
{
  GNUNET_HashCode *ctx;

  ctx = GNUNET_malloc (sizeof (GNUNET_HashCode) + ntohl (dbv->size));
  *ctx = *query;
  memcpy (&ctx[1], dbv, ntohl (dbv->size));
  GNUNET_cron_add_job (coreAPI->cron, &async_delete_job, 0, 0, ctx);
}

/**
 * A query on the datastore resulted in the on-demand
 * block dbv.  On-demand encode the block and return
 * the resulting DSV in enc.  If the on-demand
 * encoding fails because the file is no longer there,
 * this function also removes the OD-Entry
 *
 * @return GNUNET_OK on success, GNUNET_SYSERR if there was an error
 */
int
GNUNET_FS_ONDEMAND_get_indexed_content (const GNUNET_DatastoreValue * dbv,
                                        const GNUNET_HashCode * query,
                                        GNUNET_DatastoreValue ** enc)
{
  char *fn;
  char *iobuf;
  int blen;
  int fileHandle;
  int ret;
  const OnDemandBlock *odb;
  GNUNET_EC_DBlock *db;
  struct stat linkStat;


  if ((ntohl (dbv->size) != sizeof (OnDemandBlock)) ||
      (ntohl (dbv->type) != GNUNET_ECRS_BLOCKTYPE_ONDEMAND))
    {
      GNUNET_GE_BREAK (coreAPI->ectx, 0);
      return GNUNET_SYSERR;
    }
  odb = (const OnDemandBlock *) dbv;
  fn = get_indexed_filename (&odb->fileId);
  if ((GNUNET_YES != GNUNET_disk_file_test (coreAPI->ectx,
                                            fn)) ||
      (-1 == (fileHandle = GNUNET_disk_file_open (coreAPI->ectx,
                                                  fn, O_LARGEFILE | O_RDONLY,
                                                  0))))
    {
      GNUNET_GE_LOG_STRERROR_FILE (coreAPI->ectx,
                                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN |
                                   GNUNET_GE_USER | GNUNET_GE_BULK, "open",
                                   fn);
      /* Is the symlink (still) there? */
      if (LSTAT (fn, &linkStat) == -1)
        delete_content_asynchronously (dbv, query);
      else
        publish_unavailable_mark (&odb->fileId);
      GNUNET_free (fn);
      return GNUNET_SYSERR;
    }

  if (GNUNET_ntohll (odb->fileOffset) != LSEEK (fileHandle,
                                                GNUNET_ntohll
                                                (odb->fileOffset), SEEK_SET))
    {
      GNUNET_GE_LOG_STRERROR_FILE (coreAPI->ectx,
                                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN |
                                   GNUNET_GE_USER | GNUNET_GE_BULK, "lseek",
                                   fn);
      GNUNET_free (fn);
      CLOSE (fileHandle);
      delete_content_asynchronously (dbv, query);
      return GNUNET_SYSERR;
    }
  db = GNUNET_malloc (sizeof (GNUNET_EC_DBlock) + ntohl (odb->blockSize));
  db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
  iobuf = (char *) &db[1];
  blen = READ (fileHandle, iobuf, ntohl (odb->blockSize));
  if (blen != ntohl (odb->blockSize))
    {
      GNUNET_GE_LOG_STRERROR_FILE (coreAPI->ectx,
                                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN |
                                   GNUNET_GE_USER | GNUNET_GE_BULK, "read",
                                   fn);
      GNUNET_free (fn);
      GNUNET_free (db);
      CLOSE (fileHandle);
      delete_content_asynchronously (dbv, query);
      return GNUNET_SYSERR;
    }
  CLOSE (fileHandle);
  ret = GNUNET_EC_file_block_encode (db,
                                     ntohl (odb->blockSize) +
                                     sizeof (GNUNET_EC_DBlock), query, enc);
  GNUNET_free (db);
  GNUNET_free (fn);
  if (ret == GNUNET_SYSERR)
    {
      GNUNET_GE_LOG (coreAPI->ectx,
                     GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
                     _
                     ("Indexed content changed (does not match its hash).\n"));
      delete_content_asynchronously (dbv, query);
      return GNUNET_SYSERR;
    }
  (*enc)->anonymity_level = dbv->anonymity_level;
  (*enc)->expiration_time = dbv->expiration_time;
  (*enc)->priority = dbv->priority;
  return GNUNET_OK;
}

/**
 * Test if the file with the given ID is
 * indexed.
 * @return GNUNET_YES if so, GNUNET_NO if not.
 */
int
GNUNET_FS_ONDEMAND_test_indexed_file (GNUNET_Datastore_ServiceAPI * datastore,
                                      const GNUNET_HashCode * fileId)
{
  struct stat filestat;
  char *fn;

  fn = get_indexed_filename (fileId);
  if (0 != STAT (fn, &filestat))
    {
      GNUNET_free (fn);
      return GNUNET_NO;
    }
  GNUNET_free (fn);
  return GNUNET_YES;
}

/**
 * Unindex the file with the given ID.  Removes the file from the
 * filesystem and all of the corresponding obd blocks from the
 * datastore.  Note that the IBlocks are NOT removed by this function.
 *
 * @param blocksize the size of each of the
 *        indexed blocks (required to break
 *        up the file properly when computing
 *        the keys of the odb blocks).
 */
int
GNUNET_FS_ONDEMAND_delete_indexed_content (struct GNUNET_GE_Context *ectx,
                                           GNUNET_Datastore_ServiceAPI *
                                           datastore, unsigned int blocksize,
                                           const GNUNET_HashCode * fileId)
{
  char *fn;
  int fd;
  int ret;
  OnDemandBlock odb;
  GNUNET_HashCode key;
  unsigned long long pos;
  unsigned long long size;
  unsigned long long delta;
  GNUNET_EC_DBlock *block;
  GNUNET_EncName enc;

  fn = get_indexed_filename (fileId);
  fd = GNUNET_disk_file_open (ectx, fn, O_RDONLY | O_LARGEFILE, 0);
  if (fd == -1)
    {
      GNUNET_free (fn);
      return GNUNET_SYSERR;
    }
  pos = 0;
  if (GNUNET_OK != GNUNET_disk_file_size (ectx, fn, &size, GNUNET_YES))
    {
      GNUNET_free (fn);
      return GNUNET_SYSERR;
    }
  block = GNUNET_malloc (sizeof (GNUNET_EC_DBlock) + blocksize);
  block->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
  while (pos < size)
    {
      delta = size - pos;
      if (delta > blocksize)
        delta = blocksize;
      if (delta != READ (fd, &block[1], delta))
        {
          GNUNET_GE_LOG_STRERROR_FILE (ectx,
                                       GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
                                       GNUNET_GE_USER | GNUNET_GE_BULK,
                                       "read", fn);
          CLOSE (fd);
          GNUNET_free (fn);
          GNUNET_free (block);
          return GNUNET_SYSERR;
        }
      odb.header.size = htonl (sizeof (OnDemandBlock));
      odb.header.type = htonl (GNUNET_ECRS_BLOCKTYPE_ONDEMAND);
      odb.header.priority = 0;
      odb.header.anonymity_level = 0;
      odb.header.expiration_time = 0;
      odb.type = htonl (GNUNET_ECRS_BLOCKTYPE_ONDEMAND);
      odb.fileOffset = GNUNET_htonll (pos);
      odb.blockSize = htonl (delta);
      odb.fileId = *fileId;
      /* compute the primary key */
      GNUNET_EC_file_block_get_query (block,
                                      delta + sizeof (GNUNET_EC_DBlock),
                                      &key);
      if ((0 <
           datastore->get (&key, GNUNET_ECRS_BLOCKTYPE_ONDEMAND,
                           &GNUNET_FS_HELPER_complete_value_from_database_callback,
                           &odb.header)) && (odb.header.expiration_time != 0))
        ret = datastore->del (&key, &odb.header);
      else                      /* not found */
        ret = GNUNET_SYSERR;
      if (ret == GNUNET_SYSERR)
        {
          IF_GELOG (ectx,
                    GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
                    GNUNET_hash_to_enc (&key, &enc));
          GNUNET_GE_LOG (ectx,
                         GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
                         _
                         ("Unindexed ODB block `%s' from offset %llu already missing from datastore.\n"),
                         &enc, pos);
        }
      pos += delta;
    }
  GNUNET_free (block);
  CLOSE (fd);
  UNLINK (fn);
  GNUNET_free (fn);
  remove_unavailable_mark (fileId);
  return GNUNET_OK;
}



int
GNUNET_FS_ONDEMAND_init (GNUNET_CoreAPIForPlugins * capi)
{
  char *tmp;

  coreAPI = capi;
  GNUNET_GC_get_configuration_value_filename (capi->cfg,
                                              "GNUNETD",
                                              "GNUNETD_HOME",
                                              GNUNET_DEFAULT_DAEMON_VAR_DIRECTORY,
                                              &tmp);
  tmp = GNUNET_realloc (tmp, strlen (tmp) + strlen ("/data/shared/") + 1);
  strcat (tmp, "/data/shared/");
  GNUNET_GC_get_configuration_value_filename (capi->cfg,
                                              "FS",
                                              "INDEX-DIRECTORY",
                                              tmp, &index_directory);
  GNUNET_free (tmp);
  GNUNET_disk_directory_create (coreAPI->ectx, index_directory);        /* just in case */

  state = capi->service_request ("state");
  if (state == NULL)
    {
      GNUNET_GE_BREAK (coreAPI->ectx, 0);
      GNUNET_free (index_directory);
      return GNUNET_SYSERR;
    }
  datastore = capi->service_request ("datastore");
  if (datastore == NULL)
    {
      GNUNET_GE_BREAK (coreAPI->ectx, 0);
      coreAPI->service_release (state);
      state = NULL;
      GNUNET_free (index_directory);
      return GNUNET_SYSERR;
    }

  return 0;
}

int
GNUNET_FS_ONDEMAND_done ()
{
  coreAPI->service_release (state);
  state = NULL;
  coreAPI->service_release (datastore);
  datastore = NULL;
  GNUNET_free (index_directory);
  index_directory = NULL;
  return 0;
}


/* end of ondemand.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -