910e62b5创建于 1月15日历史提交
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_DRIVE_RESOURCE_METADATA_STORAGE_H_
#define COMPONENTS_DRIVE_RESOURCE_METADATA_STORAGE_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "components/drive/drive.pb.h"
#include "components/drive/drive_export.h"
#include "components/drive/file_errors.h"

namespace base {
class SequencedTaskRunner;
}

namespace leveldb {
class DB;
class Iterator;
}

namespace drive {

class ResourceEntry;
class ResourceMetadataHeader;

namespace internal {

// Storage for ResourceMetadata which is responsible to manage resource
// entries and child-parent relationships between entries.
class COMPONENTS_DRIVE_EXPORT ResourceMetadataStorage {
 public:
  // This should be incremented when incompatibility change is made to DB
  // format.
  static constexpr int kDBVersion = 19;

  // Object to iterate over entries stored in this storage.
  class COMPONENTS_DRIVE_EXPORT Iterator {
   public:
    explicit Iterator(std::unique_ptr<leveldb::Iterator> it);

    Iterator(const Iterator&) = delete;
    Iterator& operator=(const Iterator&) = delete;

    ~Iterator();

    // Returns true if this iterator cannot advance any more and does not point
    // to a valid entry. Get() and Advance() should not be called in such cases.
    bool IsAtEnd() const;

    // Returns the ID of the entry currently pointed by this object.
    std::string GetID() const;

    // Returns the entry currently pointed by this object.
    const ResourceEntry& GetValue() const;

    // Advances to the next entry.
    void Advance();

    // Returns true if this object has encountered any error.
    bool HasError() const;

   private:
    ResourceEntry entry_;
    std::unique_ptr<leveldb::Iterator> it_;
  };

  // Cache information recovered from trashed DB.
  struct COMPONENTS_DRIVE_EXPORT RecoveredCacheInfo {
    RecoveredCacheInfo();
    ~RecoveredCacheInfo();

    bool is_dirty;
    std::string md5;
    std::string title;
  };
  using RecoveredCacheInfoMap = std::map<std::string, RecoveredCacheInfo>;

  // Returns true if the DB was successfully upgraded to the newest version.
  static bool UpgradeOldDB(const base::FilePath& directory_path);

  ResourceMetadataStorage(const base::FilePath& directory_path,
                          base::SequencedTaskRunner* blocking_task_runner);

  ResourceMetadataStorage(const ResourceMetadataStorage&) = delete;
  ResourceMetadataStorage& operator=(const ResourceMetadataStorage&) = delete;

  const base::FilePath& directory_path() const { return directory_path_; }

  // Returns true when cache entries were not loaded to the DB during
  // initialization.
  bool cache_file_scan_is_needed() const { return cache_file_scan_is_needed_; }

  // Initializes this object.
  bool Initialize();

  // Destroys this object.
  void Destroy();

  // Collects cache info from trashed resource map DB.
  void RecoverCacheInfoFromTrashedResourceMap(RecoveredCacheInfoMap* out_info);

  // Sets the largest changestamp.
  FileError SetLargestChangestamp(int64_t largest_changestamp);

  // Gets the largest changestamp.
  FileError GetLargestChangestamp(int64_t* largest_changestamp);

  FileError GetStartPageToken(std::string* out_value);

  FileError SetStartPageToken(const std::string& value);

  // Puts the entry to this storage.
  FileError PutEntry(const ResourceEntry& entry);

  // Gets an entry stored in this storage.
  FileError GetEntry(const std::string& id, ResourceEntry* out_entry);

  // Removes an entry from this storage.
  FileError RemoveEntry(const std::string& id);

  // Returns an object to iterate over entries stored in this storage.
  std::unique_ptr<Iterator> GetIterator();

  // Returns the ID of the parent's child.
  FileError GetChild(const std::string& parent_id,
                     const std::string& child_name,
                     std::string* child_id) const;

  // Returns the IDs of the parent's children.
  FileError GetChildren(const std::string& parent_id,
                        std::vector<std::string>* children) const;

  // Returns the local ID associated with the given resource ID.
  FileError GetIdByResourceId(const std::string& resource_id,
                              std::string* out_id) const;

 private:
  friend class ResourceMetadataStorageTest;

  // To destruct this object, use Destroy().
  ~ResourceMetadataStorage();

  // Used to implement Destroy().
  void DestroyOnBlockingPool();

  // Returns a string to be used as a key for child entry.
  // Exposed in the header for unit testing.
  static std::string GetChildEntryKey(const std::string& parent_id,
                                      const std::string& child_name);

  // Puts header.
  FileError PutHeader(const ResourceMetadataHeader& header);

  // Gets header.
  FileError GetHeader(ResourceMetadataHeader* out_header) const;

  // Checks validity of the data.
  bool CheckValidity();

  // Path to the directory where the data is stored.
  const base::FilePath directory_path_;

  bool cache_file_scan_is_needed_;

  // Entries stored in this storage.
  std::unique_ptr<leveldb::DB> resource_map_;

  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
};

}  // namespace internal
}  // namespace drive

#endif  // COMPONENTS_DRIVE_RESOURCE_METADATA_STORAGE_H_