diff --git a/Microsoft.WindowsAzure.Storage/includes/was/blob.h b/Microsoft.WindowsAzure.Storage/includes/was/blob.h
index 72cfb5f2..4d0636ab 100644
--- a/Microsoft.WindowsAzure.Storage/includes/was/blob.h
+++ b/Microsoft.WindowsAzure.Storage/includes/was/blob.h
@@ -830,236 +830,6 @@ namespace azure { namespace storage {
int64_t m_append_position;
};
- ///
- /// The lease state of a resource.
- ///
- enum class lease_state
- {
- ///
- /// The lease state is not specified.
- ///
- unspecified,
-
- ///
- /// The lease is in the Available state.
- ///
- available,
-
- ///
- /// The lease is in the Leased state.
- ///
- leased,
-
- ///
- /// The lease is in the Expired state.
- ///
- expired,
-
- ///
- /// The lease is in the Breaking state.
- ///
- breaking,
-
- ///
- /// The lease is in the Broken state.
- ///
- broken,
- };
-
- ///
- /// The lease status of a resource.
- ///
- enum class lease_status
- {
- ///
- /// The lease status is not specified.
- ///
- unspecified,
-
- ///
- /// The resource is locked.
- ///
- locked,
-
- ///
- /// The resource is available to be locked.
- ///
- unlocked
- };
-
- ///
- /// Specifies the proposed duration of seconds that the lease should continue before it is broken.
- ///
- class lease_break_period
- {
- public:
- ///
- /// Initializes a new instance of the class that breaks
- /// a fixed-duration lease after the remaining lease period elapses, or breaks an infinite lease immediately.
- ///
- lease_break_period()
- : m_seconds(std::chrono::seconds::max())
- {
- }
-
- ///
- /// Initializes a new instance of the class that breaks
- /// a lease after the proposed duration.
- ///
- /// The proposed duration, in seconds, for the lease before it is broken. Value may
- /// be between 0 and 60 seconds.
- lease_break_period(const std::chrono::seconds& seconds)
- : m_seconds(seconds)
- {
- if (seconds != std::chrono::seconds::max())
- {
- utility::assert_in_bounds(_XPLATSTR("seconds"), seconds, protocol::minimum_lease_break_period, protocol::maximum_lease_break_period);
- }
- }
-
-#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
- // have implicitly-declared move constructor and move assignment operator.
-
- ///
- /// Initializes a new instance of the class based on an existing instance.
- ///
- /// An existing object.
- lease_break_period(lease_break_period&& other)
- {
- *this = std::move(other);
- }
-
- ///
- /// Returns a reference to an object.
- ///
- /// An existing object to use to set properties.
- /// An object with properties set.
- lease_break_period& operator=(lease_break_period&& other)
- {
- if (this != &other)
- {
- m_seconds = std::move(other.m_seconds);
- }
- return *this;
- }
-#endif
-
- ///
- /// Indicates whether the object is valid.
- ///
- /// true if the object is valid; otherwise, false.
- bool is_valid() const
- {
- return m_seconds < std::chrono::seconds::max();
- }
-
- ///
- /// Gets the proposed duration for the lease before it is broken.
- ///
- /// The proposed proposed duration for the lease before it is broken, in seconds.
- const std::chrono::seconds& seconds() const
- {
- return m_seconds;
- }
-
- private:
-
- std::chrono::seconds m_seconds;
- };
-
- ///
- /// The lease duration for a Blob service resource.
- ///
- enum class lease_duration
- {
- ///
- /// The lease duration is not specified.
- ///
- unspecified,
-
- ///
- /// The lease duration is finite.
- ///
- fixed,
-
- ///
- /// The lease duration is infinite.
- ///
- infinite,
- };
-
- ///
- /// Specifies the duration of the lease.
- ///
- class lease_time
- {
- public:
- ///
- /// Initializes a new instance of the class that never expires.
- ///
- lease_time()
- : m_seconds(-1)
- {
- }
-
- ///
- /// Initializes a new instance of the class that expires after the
- /// specified duration.
- ///
- /// The duration of the lease in seconds. For a non-infinite lease, this value can be
- /// between 15 and 60 seconds.
- lease_time(const std::chrono::seconds& seconds)
- : m_seconds(seconds)
- {
- if (seconds.count() != -1)
- {
- utility::assert_in_bounds(_XPLATSTR("seconds"), seconds, protocol::minimum_fixed_lease_duration, protocol::maximum_fixed_lease_duration);
- }
- }
-
-#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
- // have implicitly-declared move constructor and move assignment operator.
-
- ///
- /// Initializes a new instance of the class based on an existing instance.
- ///
- /// An existing object.
- lease_time(lease_time&& other)
- {
- *this = std::move(other);
- }
-
- ///
- /// Returns a reference to an object.
- ///
- /// An existing object to use to set properties.
- /// An object with properties set.
- lease_time& operator=(lease_time&& other)
- {
- if (this != &other)
- {
- m_seconds = std::move(other.m_seconds);
- }
- return *this;
- }
-#endif
-
- ///
- /// Gets the duration of the lease in seconds for a non-infinite lease.
- ///
- /// The duration of the lease.
- const std::chrono::seconds& seconds() const
- {
- return m_seconds;
- }
-
- private:
-
- std::chrono::seconds m_seconds;
- };
-
///
/// The tier of the block blob on a standard storage account.
///
diff --git a/Microsoft.WindowsAzure.Storage/includes/was/core.h b/Microsoft.WindowsAzure.Storage/includes/was/core.h
index 7e7aefb3..7e4d446a 100644
--- a/Microsoft.WindowsAzure.Storage/includes/was/core.h
+++ b/Microsoft.WindowsAzure.Storage/includes/was/core.h
@@ -118,7 +118,7 @@ namespace azure { namespace storage {
WASTORAGE_API storage_uri(web::http::uri primary_uri, web::http::uri secondary_uri);
#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
// have implicitly-declared move constructor and move assignment operator.
///
@@ -289,7 +289,7 @@ namespace azure { namespace storage {
public:
utility::string_t m_bearer_token;
-
+
private:
pplx::extensibility::reader_writer_lock_t m_mutex;
@@ -733,7 +733,7 @@ namespace azure { namespace storage {
}
#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
// have implicitly-declared move constructor and move assignment operator.
///
@@ -859,7 +859,7 @@ namespace azure { namespace storage {
}
#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
// have implicitly-declared move constructor and move assignment operator.
///
@@ -977,7 +977,7 @@ namespace azure { namespace storage {
WASTORAGE_API request_result(utility::datetime start_time, storage_location target_location, const web::http::http_response& response, web::http::status_code http_status_code, storage_extended_error extended_error);
#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 r-value reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // Compilers that fully support C++ 11 r-value reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
// have implicitly-declared move constructor and move assignment operator.
///
@@ -1271,7 +1271,7 @@ namespace azure { namespace storage {
}
#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
// have implicitly-declared move constructor and move assignment operator.
///
@@ -1382,7 +1382,7 @@ namespace azure { namespace storage {
}
#if defined(_MSC_VER) && _MSC_VER < 1900
- // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
// have implicitly-declared move constructor and move assignment operator.
///
@@ -1556,6 +1556,236 @@ namespace azure { namespace storage {
std::shared_ptr m_policy;
};
+ ///
+ /// The lease state of a resource.
+ ///
+ enum class lease_state
+ {
+ ///
+ /// The lease state is not specified.
+ ///
+ unspecified,
+
+ ///
+ /// The lease is in the Available state.
+ ///
+ available,
+
+ ///
+ /// The lease is in the Leased state.
+ ///
+ leased,
+
+ ///
+ /// The lease is in the Expired state.
+ ///
+ expired,
+
+ ///
+ /// The lease is in the Breaking state.
+ ///
+ breaking,
+
+ ///
+ /// The lease is in the Broken state.
+ ///
+ broken,
+ };
+
+ ///
+ /// The lease status of a resource.
+ ///
+ enum class lease_status
+ {
+ ///
+ /// The lease status is not specified.
+ ///
+ unspecified,
+
+ ///
+ /// The resource is locked.
+ ///
+ locked,
+
+ ///
+ /// The resource is available to be locked.
+ ///
+ unlocked
+ };
+
+ ///
+ /// Specifies the proposed duration of seconds that the lease should continue before it is broken.
+ ///
+ class lease_break_period
+ {
+ public:
+ ///
+ /// Initializes a new instance of the class that breaks
+ /// a fixed-duration lease after the remaining lease period elapses, or breaks an infinite lease immediately.
+ ///
+ lease_break_period()
+ : m_seconds(std::chrono::seconds::max())
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class that breaks
+ /// a lease after the proposed duration.
+ ///
+ /// The proposed duration, in seconds, for the lease before it is broken. Value may
+ /// be between 0 and 60 seconds.
+ lease_break_period(const std::chrono::seconds& seconds)
+ : m_seconds(seconds)
+ {
+ if (seconds != std::chrono::seconds::max())
+ {
+ utility::assert_in_bounds(_XPLATSTR("seconds"), seconds, protocol::minimum_lease_break_period, protocol::maximum_lease_break_period);
+ }
+ }
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // have implicitly-declared move constructor and move assignment operator.
+
+ ///
+ /// Initializes a new instance of the class based on an existing instance.
+ ///
+ /// An existing object.
+ lease_break_period(lease_break_period&& other)
+ {
+ *this = std::move(other);
+ }
+
+ ///
+ /// Returns a reference to an object.
+ ///
+ /// An existing object to use to set properties.
+ /// An object with properties set.
+ lease_break_period& operator=(lease_break_period&& other)
+ {
+ if (this != &other)
+ {
+ m_seconds = std::move(other.m_seconds);
+ }
+ return *this;
+ }
+#endif
+
+ ///
+ /// Indicates whether the object is valid.
+ ///
+ /// true if the object is valid; otherwise, false.
+ bool is_valid() const
+ {
+ return m_seconds < std::chrono::seconds::max();
+ }
+
+ ///
+ /// Gets the proposed duration for the lease before it is broken.
+ ///
+ /// The proposed proposed duration for the lease before it is broken, in seconds.
+ const std::chrono::seconds& seconds() const
+ {
+ return m_seconds;
+ }
+
+ private:
+
+ std::chrono::seconds m_seconds;
+ };
+
+ ///
+ /// The lease duration for a Blob service resource.
+ ///
+ enum class lease_duration
+ {
+ ///
+ /// The lease duration is not specified.
+ ///
+ unspecified,
+
+ ///
+ /// The lease duration is finite.
+ ///
+ fixed,
+
+ ///
+ /// The lease duration is infinite.
+ ///
+ infinite,
+ };
+
+ ///
+ /// Specifies the duration of the lease.
+ ///
+ class lease_time
+ {
+ public:
+ ///
+ /// Initializes a new instance of the class that never expires.
+ ///
+ lease_time()
+ : m_seconds(-1)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class that expires after the
+ /// specified duration.
+ ///
+ /// The duration of the lease in seconds. For a non-infinite lease, this value can be
+ /// between 15 and 60 seconds.
+ lease_time(const std::chrono::seconds& seconds)
+ : m_seconds(seconds)
+ {
+ if (seconds.count() != -1)
+ {
+ utility::assert_in_bounds(_XPLATSTR("seconds"), seconds, protocol::minimum_fixed_lease_duration, protocol::maximum_fixed_lease_duration);
+ }
+ }
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // have implicitly-declared move constructor and move assignment operator.
+
+ ///
+ /// Initializes a new instance of the class based on an existing instance.
+ ///
+ /// An existing object.
+ lease_time(lease_time&& other)
+ {
+ *this = std::move(other);
+ }
+
+ ///
+ /// Returns a reference to an object.
+ ///
+ /// An existing object to use to set properties.
+ /// An object with properties set.
+ lease_time& operator=(lease_time&& other)
+ {
+ if (this != &other)
+ {
+ m_seconds = std::move(other.m_seconds);
+ }
+ return *this;
+ }
+#endif
+
+ ///
+ /// Gets the duration of the lease in seconds for a non-infinite lease.
+ ///
+ /// The duration of the lease.
+ const std::chrono::seconds& seconds() const
+ {
+ return m_seconds;
+ }
+
+ private:
+
+ std::chrono::seconds m_seconds;
+ };
+
#ifdef _WIN32
///
/// Interface for scheduling tasks that start after a provided delay in milliseconds
diff --git a/Microsoft.WindowsAzure.Storage/includes/was/file.h b/Microsoft.WindowsAzure.Storage/includes/was/file.h
index c892b8bb..26c720f1 100644
--- a/Microsoft.WindowsAzure.Storage/includes/was/file.h
+++ b/Microsoft.WindowsAzure.Storage/includes/was/file.h
@@ -51,19 +51,83 @@ namespace azure { namespace storage {
class file_access_condition
{
public:
+ ///
+ /// Constructs an empty file access condition.
+ ///
file_access_condition()
- : m_valid(false)
{
}
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+,
+ // have implicitly-declared move constructor and move assignment operator.
+
+ ///
+ /// Initializes a new instance of the class based on an existing instance.
+ ///
+ /// An existing object.
+ file_access_condition(file_access_condition&& other)
+ {
+ *this = std::move(other);
+ }
+
+ ///
+ /// Returns a reference to an object.
+ ///
+ /// An existing object to use to set properties.
+ /// An object with properties set.
+ file_access_condition& operator=(file_access_condition&& other)
+ {
+ if (this != &other)
+ {
+ m_lease_id = std::move(other.m_lease_id);
+ }
+ return *this;
+ }
+#endif
+
+ ///
+ /// Generates a file access condition such that an operation will be performed only if the lease ID on the
+ /// resource matches the specified lease ID.
+ ///
+ /// The lease ID that must match the lease ID of the resource.
+ /// An object that represents the lease condition.
+ static file_access_condition generate_lease_condition(utility::string_t lease_id)
+ {
+ file_access_condition condition;
+ condition.set_lease_id(std::move(lease_id));
+ return condition;
+ }
+
+ ///
+ /// Returns if this condition is empty.
+ ///
+ /// true if this condition is empty, false otherwise.
bool is_valid() const
{
- return m_valid;
+ return !m_lease_id.empty();
}
- private:
+ ///
+ /// Gets a lease ID that must match the lease on a resource.
+ ///
+ /// A string containing the lease ID.
+ const utility::string_t& lease_id() const
+ {
+ return m_lease_id;
+ }
- bool m_valid;
+ ///
+ /// Sets a lease ID that must match the lease on a resource.
+ ///
+ /// A string containing the lease ID.
+ void set_lease_id(utility::string_t value)
+ {
+ m_lease_id = std::move(value);
+ }
+
+ private:
+ utility::string_t m_lease_id;
};
///
@@ -2700,6 +2764,8 @@ namespace azure { namespace storage {
/// Initializes a new instance of the class.
///
cloud_file_properties()
+ : m_lease_status(azure::storage::lease_status::unspecified), m_lease_state(azure::storage::lease_state::unspecified),
+ m_lease_duration(azure::storage::lease_duration::unspecified)
{
}
@@ -2739,8 +2805,11 @@ namespace azure { namespace storage {
m_last_write_time_now = std::move(other.m_last_write_time_now);
m_last_write_time_preserve = std::move(other.m_last_write_time_preserve);
m_change_time = std::move(other.m_change_time);
- m_file_id = std::move(m_file_id);
- m_parent_id = std::move(m_parent_id);
+ m_file_id = std::move(other.m_file_id);
+ m_parent_id = std::move(other.m_parent_id);
+ m_lease_status = std::move(other.m_lease_status);
+ m_lease_state = std::move(other.m_lease_state);
+ m_lease_duration = std::move(other.m_lease_duration);
}
return *this;
}
@@ -3118,6 +3187,33 @@ namespace azure { namespace storage {
return m_parent_id;
}
+ ///
+ /// Gets the file's lease status.
+ ///
+ /// An object that indicates the file's lease status.
+ azure::storage::lease_status lease_status() const
+ {
+ return m_lease_status;
+ }
+
+ ///
+ /// Gets the file's lease state.
+ ///
+ /// An object that indicates the file's lease state.
+ azure::storage::lease_state lease_state() const
+ {
+ return m_lease_state;
+ }
+
+ ///
+ /// Gets the file's lease duration.
+ ///
+ /// An object that indicates the file's lease duration.
+ azure::storage::lease_duration lease_duration() const
+ {
+ return m_lease_duration;
+ }
+
private:
utility::size64_t m_length{ 0 };
@@ -3146,9 +3242,13 @@ namespace azure { namespace storage {
utility::datetime m_change_time;
utility::string_t m_file_id;
utility::string_t m_parent_id;
+ azure::storage::lease_status m_lease_status;
+ azure::storage::lease_state m_lease_state;
+ azure::storage::lease_duration m_lease_duration;
void update_etag_and_last_modified(const cloud_file_properties& other);
void update_acl_attributes_filetime_and_fileid(const cloud_file_properties& other);
+ void update_lease(const cloud_file_properties& other);
friend class cloud_file;
friend class protocol::file_response_parsers;
@@ -4696,6 +4796,224 @@ namespace azure { namespace storage {
return *m_copy_state;
}
+ ///
+ /// Acquires a lease on the file.
+ ///
+ /// A string representing the proposed lease ID for the new lease. May be an empty string if no lease ID is proposed.
+ /// A string containing the lease ID.
+ utility::string_t acquire_lease(const utility::string_t& proposed_lease_id) const
+ {
+ return acquire_lease_async(proposed_lease_id).get();
+ }
+
+ ///
+ /// Acquires a lease on the file.
+ ///
+ /// A string representing the proposed lease ID for the new lease. May be an empty string if no lease ID is proposed.
+ /// An object that represents the access condition for the operation.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// A string containing the lease ID.
+ utility::string_t acquire_lease(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return acquire_lease_async(proposed_lease_id, condition, options, context).get();
+ }
+
+ ///
+ /// Initiates an asynchronous operation to acquire a lease on the file.
+ ///
+ /// A string representing the proposed lease ID for the new lease. May be an empty string if no lease ID is proposed.
+ /// A object of type that represents the current operation.
+ pplx::task acquire_lease_async(const utility::string_t& proposed_lease_id) const
+ {
+ return acquire_lease_async(proposed_lease_id, file_access_condition(), file_request_options(), operation_context());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to acquire a lease on the file.
+ ///
+ /// A string representing the proposed lease ID for the new lease. May be an empty string if no lease ID is proposed.
+ /// An object that represents the access condition for the operation.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// A object of type that represents the current operation.
+ pplx::task acquire_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return acquire_lease_async(proposed_lease_id, condition, options, context, pplx::cancellation_token::none());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to acquire a lease on the file.
+ ///
+ /// A string representing the proposed lease ID for the new lease. May be an empty string if no lease ID is proposed.
+ /// An object that represents the access condition for the operation.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// An object that is used to cancel the current operation.
+ /// A object of type that represents the current operation.
+ WASTORAGE_API pplx::task acquire_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const;
+
+ ///
+ /// Changes the lease ID on the file.
+ ///
+ /// A string containing the proposed lease ID for the lease. May not be empty.
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// The new lease ID.
+ utility::string_t change_lease(const utility::string_t& proposed_lease_id, const file_access_condition& condition) const
+ {
+ return change_lease_async(proposed_lease_id, condition).get();
+ }
+
+ ///
+ /// Changes the lease ID on the file.
+ ///
+ /// A string containing the proposed lease ID for the lease. May not be empty.
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// The new lease ID.
+ utility::string_t change_lease(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return change_lease_async(proposed_lease_id, condition, options, context).get();
+ }
+
+ ///
+ /// Initiates an asynchronous operation to change the lease ID on the file.
+ ///
+ /// A string containing the proposed lease ID for the lease. May not be empty.
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// A object of type that represents the current operation.
+ pplx::task change_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition) const
+ {
+ return change_lease_async(proposed_lease_id, condition, file_request_options(), operation_context());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to change the lease ID on the file.
+ ///
+ /// A string containing the proposed lease ID for the lease. May not be empty.
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// A object of type that represents the current operation.
+ pplx::task change_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return change_lease_async(proposed_lease_id, condition, options, context, pplx::cancellation_token::none());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to change the lease ID on the file.
+ ///
+ /// A string containing the proposed lease ID for the lease. May not be empty.
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// An object that is used to cancel the current operation.
+ /// A object of type that represents the current operation.
+ WASTORAGE_API pplx::task change_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const;
+
+ ///
+ /// Releases the lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ void release_lease(const file_access_condition& condition) const
+ {
+ release_lease_async(condition).wait();
+ }
+
+ ///
+ /// Releases the lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ void release_lease(const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ release_lease_async(condition, options, context).wait();
+ }
+
+ ///
+ /// Initiates an asynchronous operation to release the lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// A object that represents the current operation.
+ pplx::task release_lease_async(const file_access_condition& condition) const
+ {
+ return release_lease_async(condition, file_request_options(), operation_context());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to release the lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// A object that represents the current operation.
+ pplx::task release_lease_async(const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return release_lease_async(condition, options, context, pplx::cancellation_token::none());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to release the lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// An object that is used to cancel the current operation.
+ /// A object that represents the current operation.
+ WASTORAGE_API pplx::task release_lease_async(const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const;
+
+ ///
+ /// Breaks the current lease on the file.
+ ///
+ void break_lease() const
+ {
+ return break_lease_async().get();
+ }
+
+ ///
+ /// Breaks the current lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ void break_lease(const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return break_lease_async(condition, options, context).get();
+ }
+
+ ///
+ /// Initiates an asynchronous operation to break the current lease on the file.
+ ///
+ /// A object that represents the current operation.
+ pplx::task break_lease_async() const
+ {
+ return break_lease_async(file_access_condition(), file_request_options(), operation_context());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to break the current lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// A object that represents the current operation.
+ pplx::task break_lease_async(const file_access_condition& condition, const file_request_options& options, operation_context context) const
+ {
+ return break_lease_async(condition, options, context, pplx::cancellation_token::none());
+ }
+
+ ///
+ /// Initiates an asynchronous operation to break the current lease on the file.
+ ///
+ /// An object that represents the access conditions for the file, including a required lease ID.
+ /// An object that specifies additional options for the request.
+ /// An object that represents the context for the current operation.
+ /// An object that is used to cancel the current operation.
+ /// A object that represents the current operation.
+ WASTORAGE_API pplx::task break_lease_async(const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const;
+
private:
void init(storage_credentials credentials);
diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h b/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h
index 59849e6f..fdec99db 100644
--- a/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h
+++ b/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h
@@ -130,19 +130,21 @@ namespace azure { namespace storage { namespace protocol {
web::http::http_request get_file_directory_properties(web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
web::http::http_request set_file_directory_properties(const cloud_file_directory_properties& properties, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
web::http::http_request set_file_directory_metadata(const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request create_file(const int64_t length, const cloud_metadata& metadata, const cloud_file_properties& properties, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request delete_file(web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request get_file_properties(web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request set_file_properties(const cloud_file_properties& properties, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request resize_with_properties(const cloud_file_properties& properties, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request set_file_metadata(const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request copy_file(const web::http::uri& source, const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request copy_file_from_blob(const web::http::uri& source, const access_condition& condition, const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request abort_copy_file(const utility::string_t& copy_id, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request list_file_ranges(utility::size64_t start_offset, utility::size64_t length, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request put_file_range(file_range range, file_range_write write, utility::string_t content_md5, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
- web::http::http_request get_file(utility::size64_t start_offset, utility::size64_t length, bool md5_validation, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
-
+ web::http::http_request create_file(const int64_t length, const cloud_metadata& metadata, const cloud_file_properties& properties, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request delete_file(const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request get_file_properties(const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request set_file_properties(const cloud_file_properties& properties, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request resize_with_properties(const cloud_file_properties& properties, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request set_file_metadata(const cloud_metadata& metadata, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request copy_file(const web::http::uri& source, const cloud_metadata& metadata, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request copy_file_from_blob(const web::http::uri& source, const access_condition& condition, const cloud_metadata& metadata, const file_access_condition& file_condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request abort_copy_file(const utility::string_t& copy_id, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request list_file_ranges(utility::size64_t start_offset, utility::size64_t length, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request put_file_range(file_range range, file_range_write write, utility::string_t content_md5, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request get_file(utility::size64_t start_offset, utility::size64_t length, bool md5_validation, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ web::http::http_request lease_file(const utility::string_t& lease_action, const utility::string_t& proposed_lease_id, const file_access_condition& condition, web::http::uri_builder& uri_builder, const std::chrono::seconds& timeout, operation_context context);
+ void add_access_condition(web::http::http_request& request, const file_access_condition& condition);
+
// Common response parsers
template
diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_file.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_file.cpp
index ba56842e..e160d09c 100644
--- a/Microsoft.WindowsAzure.Storage/src/cloud_file.cpp
+++ b/Microsoft.WindowsAzure.Storage/src/cloud_file.cpp
@@ -52,13 +52,20 @@ namespace azure { namespace storage {
m_parent_id = other.m_parent_id;
}
+ void cloud_file_properties::update_lease(const cloud_file_properties& other)
+ {
+ m_lease_status = other.m_lease_status;
+ m_lease_state = other.m_lease_state;
+ m_lease_duration = other.m_lease_duration;
+ }
+
cloud_file::cloud_file(storage_uri uri)
: m_uri(std::move(uri)), m_metadata(std::make_shared()), m_properties(std::make_shared()),
m_copy_state(std::make_shared())
{
init(std::move(storage_credentials()));
}
-
+
cloud_file::cloud_file(storage_uri uri, storage_credentials credentials)
: m_uri(std::move(uri)), m_metadata(std::make_shared()), m_properties(std::make_shared()),
m_copy_state(std::make_shared())
@@ -97,14 +104,13 @@ namespace azure { namespace storage {
pplx::task cloud_file::create_async(int64_t length, const file_access_condition& access_condition, const file_request_options& options, operation_context context)
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
auto properties = m_properties;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::create_file, length, metadata(), this->properties(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::create_file, length, metadata(), this->properties(), access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties, length](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -144,14 +150,13 @@ namespace azure { namespace storage {
pplx::task cloud_file::delete_file_async(const file_access_condition& access_condition, const file_request_options& options, operation_context context)
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
auto properties = m_properties;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::delete_file, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::delete_file, access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -187,7 +192,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::download_attributes_async(const file_access_condition& access_condition, const file_request_options& options, operation_context context)
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -196,7 +200,7 @@ namespace azure { namespace storage {
auto copy_state = m_copy_state;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::get_file_properties, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::get_file_properties, access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([metadata, properties, copy_state](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -210,14 +214,13 @@ namespace azure { namespace storage {
pplx::task cloud_file::upload_properties_async(const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
auto properties = m_properties;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::set_file_properties, this->properties(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::set_file_properties, this->properties(), access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -232,14 +235,13 @@ namespace azure { namespace storage {
pplx::task cloud_file::upload_metadata_async(const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
auto properties = m_properties;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::set_file_metadata, this->metadata(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::set_file_metadata, this->metadata(), access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -253,7 +255,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::start_copy_async(const web::http::uri& source, const file_access_condition& source_condition, const file_access_condition& dest_condition, const file_request_options& options, operation_context context) const
{
UNREFERENCED_PARAMETER(source_condition);
- UNREFERENCED_PARAMETER(dest_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -261,7 +262,7 @@ namespace azure { namespace storage {
auto copy_state = m_copy_state;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::copy_file, source, this->metadata(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::copy_file, source, this->metadata(), dest_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties, copy_state](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -284,7 +285,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::start_copy_async(const web::http::uri& source, const access_condition& source_condition, const file_access_condition& dest_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(dest_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -292,7 +292,7 @@ namespace azure { namespace storage {
auto copy_state = m_copy_state;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::copy_file_from_blob, source, source_condition, this->metadata(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::copy_file_from_blob, source, source_condition, this->metadata(), dest_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties, copy_state](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -321,27 +321,25 @@ namespace azure { namespace storage {
pplx::task cloud_file::abort_copy_async(const utility::string_t& copy_id, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::abort_copy_file, copy_id, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::abort_copy_file, copy_id, access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
return core::executor::execute_async(command, modified_options, context);
}
-
+
pplx::task> cloud_file::list_ranges_async(utility::size64_t start_offset, utility::size64_t length, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
auto properties = m_properties;
auto command = std::make_shared>>(uri());
- command->set_build_request(std::bind(protocol::list_file_ranges, start_offset, length, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::list_file_ranges, start_offset, length, access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context) -> std::vector
{
@@ -364,7 +362,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::clear_range_async(utility::size64_t start_offset, utility::size64_t length, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -373,7 +370,7 @@ namespace azure { namespace storage {
file_range range(start_offset, end_offset);
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::put_file_range, range, file_range_write::clear, utility::string_t(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::put_file_range, range, file_range_write::clear, utility::string_t(), access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -384,10 +381,9 @@ namespace azure { namespace storage {
});
return core::executor::execute_async(command, modified_options, context);
}
-
+
pplx::task cloud_file::write_range_async(Concurrency::streams::istream stream, int64_t start_offset, const utility::string_t& content_md5, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -403,12 +399,12 @@ namespace azure { namespace storage {
properties->update_etag_and_last_modified(modified_properties);
properties->m_content_md5 = modified_properties.content_md5();
});
- return core::istream_descriptor::create(stream, needs_md5 ? checksum_type::md5 : checksum_type::none, std::numeric_limits::max(), protocol::max_range_size).then([command, context, start_offset, content_md5, modified_options](core::istream_descriptor request_body)->pplx::task
+ return core::istream_descriptor::create(stream, needs_md5 ? checksum_type::md5 : checksum_type::none, std::numeric_limits::max(), protocol::max_range_size).then([command, context, start_offset, content_md5, access_condition, modified_options](core::istream_descriptor request_body)->pplx::task
{
const utility::string_t& md5 = content_md5.empty() ? request_body.content_checksum().md5() : content_md5;
auto end_offset = start_offset + request_body.length() - 1;
file_range range(start_offset, end_offset);
- command->set_build_request(std::bind(protocol::put_file_range, range, file_range_write::update, md5, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::put_file_range, range, file_range_write::update, md5, access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_request_body(request_body);
return core::executor::execute_async(command, modified_options, context);
});
@@ -427,7 +423,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::download_single_range_to_stream_async(concurrency::streams::ostream target, utility::size64_t offset, utility::size64_t length, const file_access_condition& condition, const file_request_options& options, operation_context context, bool update_properties, bool validate_last_modify) const
{
- UNREFERENCED_PARAMETER(condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -444,7 +439,7 @@ namespace azure { namespace storage {
std::shared_ptr> command = std::make_shared>(uri());
std::weak_ptr> weak_command(command);
- command->set_build_request([offset, length, modified_options, download_info](web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context) -> web::http::http_request
+ command->set_build_request([offset, length, condition, modified_options, download_info](web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context) -> web::http::http_request
{
utility::size64_t current_offset = offset;
utility::size64_t current_length = length;
@@ -469,7 +464,7 @@ namespace azure { namespace storage {
}
}
- return protocol::get_file(current_offset, current_length, modified_options.use_transactional_md5() && !download_info->m_are_properties_populated, uri_builder, timeout, context);
+ return protocol::get_file(current_offset, current_length, modified_options.use_transactional_md5() && !download_info->m_are_properties_populated, condition, uri_builder, timeout, context);
});
command->set_authentication_handler(service_client().authentication_handler());
command->set_location_mode(core::command_location_mode::primary_or_secondary);
@@ -547,7 +542,7 @@ namespace azure { namespace storage {
throw storage_exception(protocol::error_missing_md5, false);
}
- // Lock to the current storage location when resuming a failed download. This is locked
+ // Lock to the current storage location when resuming a failed download. This is locked
// early before the retry policy has the opportunity to change the storage location.
command->set_location_mode(core::command_location_mode::primary_or_secondary, result.target_location());
@@ -797,7 +792,7 @@ namespace azure { namespace storage {
return core::cloud_file_ostreambuf(instance, instance->properties().length(), access_condition, modified_options, context).create_ostream();
});
}
-
+
pplx::task cloud_file::open_write_async(utility::size64_t length, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
file_request_options modified_options(options);
@@ -809,7 +804,7 @@ namespace azure { namespace storage {
return core::cloud_file_ostreambuf(instance, length, access_condition, modified_options, context).create_ostream();
});
}
-
+
pplx::task cloud_file::upload_from_stream_async(concurrency::streams::istream source, utility::size64_t length, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
file_request_options modified_options(options);
@@ -832,7 +827,7 @@ namespace azure { namespace storage {
});
});
}
-
+
pplx::task cloud_file::upload_from_file_async(const utility::string_t& path, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
auto instance = std::make_shared(*this);
@@ -847,7 +842,7 @@ namespace azure { namespace storage {
});
});
}
-
+
pplx::task cloud_file::upload_text_async(const utility::string_t& text, const file_access_condition& condition, const file_request_options& options, operation_context context) const
{
auto utf8_body = utility::conversions::to_utf8string(text);
@@ -859,7 +854,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::resize_async(int64_t length, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -867,7 +861,7 @@ namespace azure { namespace storage {
properties->m_length = length;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::resize_with_properties, this->properties(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::resize_with_properties, this->properties(), access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context)
{
@@ -910,7 +904,6 @@ namespace azure { namespace storage {
pplx::task cloud_file::exists_async(bool primary_only, const file_access_condition& access_condition, const file_request_options& options, operation_context context) const
{
- UNREFERENCED_PARAMETER(access_condition);
file_request_options modified_options(options);
modified_options.apply_defaults(service_client().default_request_options());
@@ -918,7 +911,7 @@ namespace azure { namespace storage {
auto metadata = m_metadata;
auto command = std::make_shared>(uri());
- command->set_build_request(std::bind(protocol::get_file_properties, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_build_request(std::bind(protocol::get_file_properties, access_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_authentication_handler(service_client().authentication_handler());
command->set_location_mode(primary_only ? core::command_location_mode::primary_only : core::command_location_mode::primary_or_secondary);
command->set_preprocess_response([properties, metadata](const web::http::http_response& response, const request_result& result, operation_context context)
@@ -935,4 +928,90 @@ namespace azure { namespace storage {
return core::executor::execute_async(command, modified_options, context);
}
-}}
\ No newline at end of file
+ pplx::task cloud_file::acquire_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const
+ {
+ file_request_options modified_options(options);
+ modified_options.apply_defaults(service_client().default_request_options());
+
+ auto properties = m_properties;
+
+ auto command = std::make_shared>(uri(), cancellation_token, modified_options.is_maximum_execution_time_customized());
+ command->set_build_request(std::bind(protocol::lease_file, protocol::header_value_lease_acquire, proposed_lease_id, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_authentication_handler(service_client().authentication_handler());
+ command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t
+ {
+ protocol::preprocess_response_void(response, result, context);
+ auto response_properties = protocol::file_response_parsers::parse_file_properties(response);
+ properties->update_etag_and_last_modified(response_properties);
+ properties->update_lease(response_properties);
+ return protocol::parse_lease_id(response);
+ });
+
+ return core::executor::execute_async(command, modified_options, context);
+ }
+
+ pplx::task cloud_file::change_lease_async(const utility::string_t& proposed_lease_id, const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const
+ {
+ file_request_options modified_options(options);
+ modified_options.apply_defaults(service_client().default_request_options());
+
+ auto properties = m_properties;
+
+ auto command = std::make_shared>(uri(), cancellation_token, modified_options.is_maximum_execution_time_customized());
+ command->set_build_request(std::bind(protocol::lease_file, protocol::header_value_lease_change, proposed_lease_id, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_authentication_handler(service_client().authentication_handler());
+ command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t
+ {
+ protocol::preprocess_response_void(response, result, context);
+ auto response_properties = protocol::file_response_parsers::parse_file_properties(response);
+ properties->update_etag_and_last_modified(response_properties);
+ properties->update_lease(response_properties);
+ return protocol::parse_lease_id(response);
+ });
+
+ return core::executor::execute_async(command, modified_options, context);
+ }
+
+ pplx::task cloud_file::release_lease_async(const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const
+ {
+ file_request_options modified_options(options);
+ modified_options.apply_defaults(service_client().default_request_options());
+
+ auto properties = m_properties;
+
+ auto command = std::make_shared>(uri(), cancellation_token, modified_options.is_maximum_execution_time_customized());
+ command->set_build_request(std::bind(protocol::lease_file, protocol::header_value_lease_release, utility::string_t(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_authentication_handler(service_client().authentication_handler());
+ command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context) -> void
+ {
+ protocol::preprocess_response_void(response, result, context);
+ auto response_properties = protocol::file_response_parsers::parse_file_properties(response);
+ properties->update_etag_and_last_modified(response_properties);
+ properties->update_lease(response_properties);
+ });
+
+ return core::executor::execute_async(command, modified_options, context);
+ }
+
+ pplx::task cloud_file::break_lease_async(const file_access_condition& condition, const file_request_options& options, operation_context context, const pplx::cancellation_token& cancellation_token) const
+ {
+ file_request_options modified_options(options);
+ modified_options.apply_defaults(service_client().default_request_options());
+
+ auto properties = m_properties;
+
+ auto command = std::make_shared>(uri(), cancellation_token, modified_options.is_maximum_execution_time_customized());
+ command->set_build_request(std::bind(protocol::lease_file, protocol::header_value_lease_break, utility::string_t(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ command->set_authentication_handler(service_client().authentication_handler());
+ command->set_preprocess_response([properties](const web::http::http_response& response, const request_result& result, operation_context context) -> void
+ {
+ protocol::preprocess_response_void(response, result, context);
+ auto response_properties = protocol::file_response_parsers::parse_file_properties(response);
+ properties->update_etag_and_last_modified(response_properties);
+ properties->update_lease(response_properties);
+ });
+
+ return core::executor::execute_async(command, modified_options, context);
+ }
+
+}}
diff --git a/Microsoft.WindowsAzure.Storage/src/file_request_factory.cpp b/Microsoft.WindowsAzure.Storage/src/file_request_factory.cpp
index 068c130c..170e74b3 100644
--- a/Microsoft.WindowsAzure.Storage/src/file_request_factory.cpp
+++ b/Microsoft.WindowsAzure.Storage/src/file_request_factory.cpp
@@ -218,6 +218,11 @@ namespace azure { namespace storage { namespace protocol {
}
}
+ void add_access_condition(web::http::http_request& request, const file_access_condition& condition)
+ {
+ add_optional_header(request.headers(), ms_header_lease_id, condition.lease_id());
+ }
+
web::http::http_request list_shares(const utility::string_t& prefix, bool get_metadata, int max_results, const continuation_token& token, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_component, component_list, /* do_encoding */ false));
@@ -365,7 +370,7 @@ namespace azure { namespace storage { namespace protocol {
return request;
}
-
+
web::http::http_request set_file_directory_metadata(const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_resource_type, resource_directory, /* do_encoding */ false));
@@ -384,7 +389,7 @@ namespace azure { namespace storage { namespace protocol {
{
uri_builder.append_query(core::make_query_parameter(uri_query_prefix, prefix));
}
-
+
if (!token.empty())
{
uri_builder.append_query(core::make_query_parameter(uri_query_marker, token.next_marker()));
@@ -399,7 +404,7 @@ namespace azure { namespace storage { namespace protocol {
return request;
}
- web::http::http_request create_file(const int64_t length, const cloud_metadata& metadata, const cloud_file_properties& properties, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request create_file(const int64_t length, const cloud_metadata& metadata, const cloud_file_properties& properties, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
@@ -410,22 +415,25 @@ namespace azure { namespace storage { namespace protocol {
add_optional_header(request.headers(), _XPLATSTR("x-ms-type"), _XPLATSTR("file"));
request.headers()[ms_header_content_length] = core::convert_to_string(length);
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request delete_file(web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request delete_file(const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
web::http::http_request request(base_request(web::http::methods::DEL, uri_builder, timeout, context));
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request get_file_properties(web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request get_file_properties(const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
web::http::http_request request(base_request(web::http::methods::HEAD, uri_builder, timeout, context));
+ add_access_condition(request, condition);
return request;
}
-
- web::http::http_request set_file_properties(const cloud_file_properties& properties, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+
+ web::http::http_request set_file_properties(const cloud_file_properties& properties, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_component, component_properties, /* do_encoding */ false));
@@ -434,71 +442,72 @@ namespace azure { namespace storage { namespace protocol {
//If resize is needed, user should call azure::storage::cloud_file::resize instead.
add_file_properties(request, properties);
add_additional_properties(request, properties, file_operation_type::update);
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request resize_with_properties(const cloud_file_properties & properties, web::http::uri_builder uri_builder, const std::chrono::seconds & timeout, operation_context context)
+ web::http::http_request resize_with_properties(const cloud_file_properties & properties, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds & timeout, operation_context context)
{
- auto request = set_file_properties(properties, uri_builder, timeout, context);
-
+ auto request = set_file_properties(properties, condition, uri_builder, timeout, context);
request.headers()[ms_header_content_length] = core::convert_to_string(properties.length());
return request;
}
-
- web::http::http_request set_file_metadata(const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+
+ web::http::http_request set_file_metadata(const cloud_metadata& metadata, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_component, component_metadata, /* do_encoding */ false));
web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
add_metadata(request, metadata);
+ add_access_condition(request, condition);
return request;
}
-
- web::http::http_request copy_file(const web::http::uri& source, const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request copy_file(const web::http::uri& source, const cloud_metadata& metadata, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
request.headers().add(ms_header_copy_source, source.to_string());
add_metadata(request, metadata);
-
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request copy_file_from_blob(const web::http::uri& source, const access_condition& condition, const cloud_metadata& metadata, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request copy_file_from_blob(const web::http::uri& source, const access_condition& condition, const cloud_metadata& metadata, const file_access_condition& file_condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
request.headers().add(ms_header_copy_source, source.to_string());
add_source_access_condition(request, condition);
add_metadata(request, metadata);
-
+ add_access_condition(request, file_condition);
return request;
}
- web::http::http_request abort_copy_file(const utility::string_t& copy_id, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request abort_copy_file(const utility::string_t& copy_id, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_component, component_copy, /* do_encoding */ false));
uri_builder.append_query(core::make_query_parameter(uri_query_copy_id, copy_id, /* do_encoding */ false));
web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
request.headers().add(ms_header_copy_action, header_value_copy_abort);
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request list_file_ranges(utility::size64_t start_offset, utility::size64_t length, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request list_file_ranges(utility::size64_t start_offset, utility::size64_t length, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_component, component_range_list, /* do_encoding */ false));
-
+
web::http::http_request request(base_request(web::http::methods::GET, uri_builder, timeout, context));
add_file_range(request, start_offset, length);
-
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request put_file_range(file_range range, file_range_write write, utility::string_t content_md5, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request put_file_range(file_range range, file_range_write write, utility::string_t content_md5, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
uri_builder.append_query(core::make_query_parameter(uri_query_component, component_range, /* do_encoding */ false));
web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
-
+
web::http::http_headers& headers = request.headers();
headers.add(ms_header_range, range.to_string());
@@ -513,10 +522,11 @@ namespace azure { namespace storage { namespace protocol {
headers.add(_XPLATSTR("x-ms-write"), _XPLATSTR("clear"));
break;
}
+ add_access_condition(request, condition);
return request;
}
- web::http::http_request get_file(utility::size64_t start_offset, utility::size64_t length, bool md5_validation, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ web::http::http_request get_file(utility::size64_t start_offset, utility::size64_t length, bool md5_validation, const file_access_condition& condition, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context)
{
web::http::http_request request(base_request(web::http::methods::GET, uri_builder, timeout, context));
web::http::http_headers& headers = request.headers();
@@ -526,6 +536,29 @@ namespace azure { namespace storage { namespace protocol {
{
headers.add(ms_header_range_get_content_md5, header_value_true);
}
+ add_access_condition(request, condition);
+ return request;
+ }
+
+ web::http::http_request lease_file(const utility::string_t& lease_action, const utility::string_t& proposed_lease_id, const file_access_condition& condition, web::http::uri_builder& uri_builder, const std::chrono::seconds& timeout, operation_context context)
+ {
+ uri_builder.append_query(core::make_query_parameter(uri_query_component, component_lease, /* do_encoding */ false));
+ web::http::http_request request(base_request(web::http::methods::PUT, uri_builder, timeout, context));
+
+ web::http::http_headers& headers = request.headers();
+ headers.add(ms_header_lease_action, lease_action);
+ if (lease_action == header_value_lease_acquire)
+ {
+ headers.add(ms_header_lease_duration, "-1");
+ add_optional_header(headers, ms_header_lease_proposed_id, proposed_lease_id);
+ }
+ else if (lease_action == header_value_lease_change)
+ {
+ add_optional_header(headers, ms_header_lease_proposed_id, proposed_lease_id);
+ }
+
+ add_access_condition(request, condition);
+
return request;
}
-}}}
\ No newline at end of file
+}}}
diff --git a/Microsoft.WindowsAzure.Storage/src/file_response_parsers.cpp b/Microsoft.WindowsAzure.Storage/src/file_response_parsers.cpp
index c8848a4e..b2082126 100644
--- a/Microsoft.WindowsAzure.Storage/src/file_response_parsers.cpp
+++ b/Microsoft.WindowsAzure.Storage/src/file_response_parsers.cpp
@@ -93,6 +93,10 @@ namespace azure { namespace storage { namespace protocol {
properties.m_file_id = get_header_value(headers, ms_header_file_id);
properties.m_parent_id = get_header_value(headers, ms_header_file_parent_id);
+ properties.m_lease_status = parse_lease_status(response);
+ properties.m_lease_state = parse_lease_state(response);
+ properties.m_lease_duration = parse_lease_duration(response);
+
return properties;
}
diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_file_directory_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_file_directory_test.cpp
index 3d321015..14eaa638 100644
--- a/Microsoft.WindowsAzure.Storage/tests/cloud_file_directory_test.cpp
+++ b/Microsoft.WindowsAzure.Storage/tests/cloud_file_directory_test.cpp
@@ -322,7 +322,7 @@ SUITE(File)
m_directory.get_subdirectory_reference(exclude_prefix + azure::storage::core::convert_to_string(i)).create();
}
- int num_items_expected = directories.size() + files.size();
+ size_t num_items_expected = directories.size() + files.size();
int num_items_actual = 0;
for (auto&& item : m_directory.list_files_and_directories(prefix))
{
diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp
index 16249adf..5685dc3c 100644
--- a/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp
+++ b/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp
@@ -48,7 +48,7 @@ SUITE(File)
CHECK(!m_file.create_if_not_exists(1024U, azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context));
CHECK_EQUAL(m_file.properties().length(), 1024U);
m_file.download_attributes();
-
+
CHECK_EQUAL(m_file.properties().server_encrypted(), true);
CHECK(m_file.exists(azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context));
@@ -159,7 +159,7 @@ SUITE(File)
m_file.upload_properties();
CHECK(m_file.properties().permission().empty());
CHECK(m_file.properties().permission_key() == properties.permission_key());
- CHECK_EQUAL(m_file.properties().attributes(), properties.attributes());
+ CHECK(m_file.properties().attributes() == properties.attributes());
CHECK(m_file.properties().creation_time() == properties.creation_time());
CHECK(m_file.properties().last_write_time() == properties.last_write_time());
CHECK(m_file.properties().file_id() == properties.file_id());
@@ -179,7 +179,7 @@ SUITE(File)
m_file.upload_properties();
CHECK(m_file.properties().permission().empty());
CHECK(!m_file.properties().permission_key().empty());
- CHECK_EQUAL(m_file.properties().attributes(), new_attributes);
+ CHECK(m_file.properties().attributes() == new_attributes);
CHECK(m_file.properties().creation_time() == current_time);
CHECK(m_file.properties().last_write_time() == current_time);
@@ -211,7 +211,7 @@ SUITE(File)
directory.upload_properties();
CHECK(directory.properties().permission().empty());
CHECK(directory.properties().permission_key() == properties.permission_key());
- CHECK_EQUAL(directory.properties().attributes(), properties.attributes());
+ CHECK(directory.properties().attributes() == properties.attributes());
CHECK(directory.properties().creation_time() == properties.creation_time());
CHECK(directory.properties().last_write_time() == properties.last_write_time());
CHECK(directory.properties().file_id() == properties.file_id());
@@ -231,7 +231,7 @@ SUITE(File)
directory.upload_properties();
CHECK(directory.properties().permission().empty());
CHECK(!directory.properties().permission_key().empty());
- CHECK_EQUAL(directory.properties().attributes(), new_attributes);
+ CHECK(directory.properties().attributes() == new_attributes);
CHECK(directory.properties().creation_time() == current_time);
CHECK(directory.properties().last_write_time() == current_time);
@@ -405,7 +405,7 @@ SUITE(File)
/// create dest files with specified sas credentials, only read access to dest read file and only write access to dest write file.
auto dest_file_name = this->get_random_string();
auto dest = m_directory.get_file_reference(dest_file_name);
-
+
/// try to copy from source blob to dest file, use dest_read_file to check copy stats.
auto copy_id = dest.start_copy(source_blob, azure::storage::access_condition(), azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context);
CHECK(wait_for_copy(dest));
@@ -537,7 +537,7 @@ SUITE(File)
{
auto range = ranges1.at(0);
CHECK(range.start_offset() == 0);
- CHECK((range.end_offset() - range.start_offset() + 1) == content.length());
+ CHECK(size_t(range.end_offset() - range.start_offset() + 1) == content.length());
}
m_file.clear_range(0, content.length());
auto ranges_clear = m_file.list_ranges(0, 2048, azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context);
@@ -547,7 +547,7 @@ SUITE(File)
{
auto range = ranges1.at(0);
CHECK(range.start_offset() == 0);
- CHECK((range.end_offset() - range.start_offset() + 1) == content.length());
+ CHECK(size_t(range.end_offset() - range.start_offset() + 1) == content.length());
}
// verify write range with total length larger than the content.
@@ -880,4 +880,185 @@ SUITE(File)
check_parallelism(context, 1);
CHECK(file.properties().size() == target_length);
}
+
+ TEST_FIXTURE(file_test_base, file_lease)
+ {
+ m_file.create(1024);
+ CHECK(azure::storage::lease_status::unspecified == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::unspecified == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+ m_file.download_attributes();
+ CHECK(azure::storage::lease_status::unlocked == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::available == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+
+ // Acquire
+ utility::string_t lease_id = m_file.acquire_lease(utility::string_t());
+ CHECK(azure::storage::lease_status::unspecified == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::unspecified == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+ m_file.download_attributes();
+ CHECK(azure::storage::lease_status::locked == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::leased == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::infinite == m_file.properties().lease_duration());
+
+ // Change
+ utility::string_t lease_id2 = utility::uuid_to_string(utility::new_uuid());
+ azure::storage::file_access_condition condition;
+ condition.set_lease_id(lease_id);
+ lease_id = m_file.change_lease(lease_id2, condition);
+ utility::details::inplace_tolower(lease_id);
+ utility::details::inplace_tolower(lease_id2);
+ CHECK(lease_id == lease_id2);
+ CHECK(azure::storage::lease_status::unspecified == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::unspecified == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+
+ // Break
+ m_file.break_lease();
+ CHECK(azure::storage::lease_status::unspecified == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::unspecified == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+ m_file.download_attributes();
+ CHECK(azure::storage::lease_status::unlocked == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::broken == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+
+ lease_id = m_file.acquire_lease(utility::string_t());
+ condition.set_lease_id(lease_id);
+ m_file.break_lease(condition, azure::storage::file_request_options(), m_context);
+
+ // Acquire with proposed lease id
+ lease_id2 = utility::uuid_to_string(utility::new_uuid());
+ lease_id = m_file.acquire_lease(lease_id2);
+ utility::details::inplace_tolower(lease_id);
+ utility::details::inplace_tolower(lease_id2);
+ CHECK(lease_id == lease_id2);
+
+ // Release
+ CHECK_THROW(m_file.release_lease(condition), azure::storage::storage_exception);
+ condition.set_lease_id(lease_id);
+ m_file.release_lease(condition);
+ CHECK(azure::storage::lease_status::unspecified == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::unspecified == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+ m_file.download_attributes();
+ CHECK(azure::storage::lease_status::unlocked == m_file.properties().lease_status());
+ CHECK(azure::storage::lease_state::available == m_file.properties().lease_state());
+ CHECK(azure::storage::lease_duration::unspecified == m_file.properties().lease_duration());
+ }
+
+ TEST_FIXTURE(file_test_base, file_operations_with_lease)
+ {
+ m_file.create(1024);
+ utility::string_t lease_id = m_file.acquire_lease(utility::string_t());
+
+ azure::storage::file_access_condition lease_condition;
+ lease_condition.set_lease_id(lease_id);
+ azure::storage::file_access_condition wrong_condition;
+ wrong_condition.set_lease_id(utility::uuid_to_string(utility::new_uuid()));
+ azure::storage::file_access_condition empty_condition;
+
+ std::vector conditions =
+ {
+ empty_condition, wrong_condition, lease_condition
+ };
+
+ utility::string_t upload_content = _XPLATSTR("content");
+ concurrency::streams::container_buffer> download_buffer;
+ auto copy_src = m_directory.get_file_reference(_XPLATSTR("copy_src"));
+ copy_src.create(1024);
+ copy_src.upload_text(upload_content);
+ utility::string_t copy_id;
+ std::vector> funcs =
+ {
+ // Create
+ [&](azure::storage::file_access_condition condition) { m_file.create(2048, condition, azure::storage::file_request_options(), m_context); },
+ // Create if not exists
+ [&](azure::storage::file_access_condition condition) { m_file.create_if_not_exists(2048, condition, azure::storage::file_request_options(), m_context); },
+ // Download attributes
+ [&](azure::storage::file_access_condition condition) { m_file.download_attributes(condition, azure::storage::file_request_options(), m_context); },
+ // Exist
+ [&](azure::storage::file_access_condition condition) { m_file.exists(condition, azure::storage::file_request_options(), m_context); },
+ // Upload properties
+ [&](azure::storage::file_access_condition condition) { m_file.upload_properties(condition, azure::storage::file_request_options(), m_context); },
+ // Upload metadata
+ [&](azure::storage::file_access_condition condition) { m_file.upload_metadata(condition, azure::storage::file_request_options(), m_context); },
+ // Resize
+ [&](azure::storage::file_access_condition condition) { m_file.resize(4096, condition, azure::storage::file_request_options(), m_context); },
+ // Upload from stream
+ [&](azure::storage::file_access_condition condition) { m_file.upload_from_stream(concurrency::streams::bytestream::open_istream(utility::conversions::to_utf8string(upload_content)), condition, azure::storage::file_request_options(), m_context); },
+ // Write range
+ [&](azure::storage::file_access_condition condition) { m_file.write_range(concurrency::streams::bytestream::open_istream(utility::conversions::to_utf8string(upload_content)), 0, utility::string_t(), condition, azure::storage::file_request_options(), m_context); },
+ // List ranges
+ [&](azure::storage::file_access_condition condition) { m_file.list_ranges(0, 4096, condition, azure::storage::file_request_options(), m_context); },
+ // Download range
+ [&](azure::storage::file_access_condition condition) { m_file.download_to_stream(download_buffer.create_ostream(), condition, azure::storage::file_request_options(), m_context); },
+ // Clear range
+ [&](azure::storage::file_access_condition condition) { m_file.clear_range(0, 1, condition, azure::storage::file_request_options(), m_context); },
+ // Start copy
+ [&](azure::storage::file_access_condition condition)
+ {
+ auto id = m_file.start_copy(copy_src.uri().primary_uri(), azure::storage::access_condition(), condition, azure::storage::file_request_options(), m_context);
+ copy_id = id.empty() ? copy_id : id;
+ },
+ // Abort copy
+ [&](azure::storage::file_access_condition condition) { m_file.abort_copy(copy_id, condition, azure::storage::file_request_options(), m_context); },
+ // Delete if exists
+ [&](azure::storage::file_access_condition condition) { m_file.delete_file_if_exists(condition, azure::storage::file_request_options(), m_context); },
+ };
+
+ std::vector> expected_results =
+ {
+ // Create
+ {0, 0, 1},
+ // Create if not exists
+ {0, 0, 1},
+ // Download Attributes
+ {1, 0, 1},
+ // Exist
+ {1, 0, 1},
+ // Upload properties
+ {0, 0, 1},
+ // Upload metadata
+ {0, 0, 1},
+ // Resize
+ {0, 0, 1},
+ // Upload from stream
+ {0, 0, 1},
+ // Write range
+ {0, 0, 1},
+ // List ranges
+ {1, 0, 1},
+ // Download range
+ {1, 0, 1},
+ // Clear range
+ {0, 0, 1},
+ // Start copy
+ {0, 0, 1},
+ // Abort copy
+ {0, 0, 1},
+ // Delete if exists
+ {0, 0, 1},
+ };
+ CHECK_EQUAL(funcs.size(), expected_results.size());
+
+ for (int i = 0; i < funcs.size(); ++i)
+ {
+ for (int j = 0; j < conditions.size(); ++j)
+ {
+ try
+ {
+ funcs[i](conditions[j]);
+ }
+ catch (azure::storage::storage_exception& e)
+ {
+ if (expected_results[i][j] == true && e.result().http_status_code() == web::http::status_codes::PreconditionFailed)
+ {
+ throw;
+ }
+ }
+ }
+ }
+ }
}