public void UpdateFileMetadata(string filename, NameValueCollection metadata)
		{
			Api.JetSetCurrentIndex(session, Files, "by_name");
			Api.MakeKey(session, Files, filename, Encoding.Unicode, MakeKeyGrbit.NewKey);
			if (Api.TrySeek(session, Files, SeekGrbit.SeekEQ) == false)
				throw new FileNotFoundException(filename);

			using (var update = new Update(session, Files, JET_prep.Replace))
			{
				if (!metadata.AllKeys.Contains("ETag"))
				{
					throw new InvalidOperationException("Metadata of file {0} does not contain 'ETag' key " + filename);
				}

				var innerEsentMetadata = new NameValueCollection(metadata);

				var etag = innerEsentMetadata.Value<Guid>("ETag");
				innerEsentMetadata.Remove("ETag");

				var existingMetadata = RetrieveMetadata();

				if (existingMetadata.AllKeys.Contains("Content-MD5"))
				{
					innerEsentMetadata["Content-MD5"] = existingMetadata["Content-MD5"];
				}

				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["etag"], etag.TransformToValueForEsentSorting());
				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["metadata"], ToQueryString(innerEsentMetadata),
				              Encoding.Unicode);

				update.Save();
			}
		}
        public void UpdateFileMetadata(string filename, NameValueCollection metadata)
        {
            var key = CreateKey(filename);

            ushort version;
            var file = LoadJson(storage.Files, key, writeBatch.Value, out version);
            if (file == null)
                throw new FileNotFoundException(filename);

            if (!metadata.AllKeys.Contains("ETag"))
                throw new InvalidOperationException(string.Format("Metadata of file {0} does not contain 'ETag' key", filename));

            var innerMetadata = new NameValueCollection(metadata);
            var etag = innerMetadata.Value<Guid>("ETag");
            innerMetadata.Remove("ETag");

            var existingMetadata = RetrieveMetadata(file);
            if (existingMetadata.AllKeys.Contains("Content-MD5"))
                innerMetadata["Content-MD5"] = existingMetadata["Content-MD5"];

	        var oldEtag = file.Value<string>("etag");

            file["etag"] = etag.ToString();
            file["metadata"] = ToQueryString(innerMetadata);

            storage.Files.Add(writeBatch.Value, key, file, version);

			var filesByEtag = storage.Files.GetIndex(Tables.Files.Indices.ByEtag);

			filesByEtag.Delete(writeBatch.Value, CreateKey(oldEtag));
			filesByEtag.Add(writeBatch.Value, CreateKey(etag), key);
        }
		public void PutFile(string filename, long? totalSize, NameValueCollection metadata, bool tombstone = false)
		{
			using (var update = new Update(session, Files, JET_prep.Insert))
			{
				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["name"], filename, Encoding.Unicode);
				if (totalSize != null)
					Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["total_size"], BitConverter.GetBytes(totalSize.Value));

				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["uploaded_size"], BitConverter.GetBytes(0));

				if (!metadata.AllKeys.Contains("ETag"))
					throw new InvalidOperationException(string.Format("Metadata of file {0} does not contain 'ETag' key", filename));

				var innerEsentMetadata = new NameValueCollection(metadata);

				var etag = innerEsentMetadata.Value<Guid>("ETag");
				innerEsentMetadata.Remove("ETag");

				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["etag"], etag.TransformToValueForEsentSorting());
				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["metadata"], ToQueryString(innerEsentMetadata),
				              Encoding.Unicode);

				update.Save();
			}

			if (!tombstone)
			{
				if (Api.TryMoveFirst(session, Details) == false)
					throw new InvalidOperationException("Could not find system metadata row");

				Api.EscrowUpdate(session, Details, tableColumnsCache.DetailsColumns["file_count"], 1);
			}
		}
        public void PutFile(string filename, long? totalSize, NameValueCollection metadata, bool tombstone = false)
        {
            var filesByEtag = storage.Files.GetIndex(Tables.Files.Indices.ByEtag);

            var key = CreateKey(filename);

            if (!metadata.AllKeys.Contains("ETag"))
                throw new InvalidOperationException(string.Format("Metadata of file {0} does not contain 'ETag' key", filename));
			
			ushort version;
	        var existingFile = LoadJson(storage.Files, key, writeBatch.Value, out version);

            var innerMetadata = new NameValueCollection(metadata);
            var etag = innerMetadata.Value<Guid>("ETag");
            innerMetadata.Remove("ETag");

            var file = new RavenJObject
                       {
                           { "name", filename }, 
                           { "total_size", totalSize }, 
                           { "uploaded_size", 0 }, 
                           { "etag", etag.ToString() }, 
                           { "metadata", ToQueryString(innerMetadata) }
                       };

            storage.Files.Add(writeBatch.Value, key, file, version);

	        if (existingFile != null)
	        {
		        filesByEtag.Delete(writeBatch.Value, CreateKey(existingFile.Value<string>("etag")));
	        }

	        filesByEtag.Add(writeBatch.Value, CreateKey(etag), key);

            if (tombstone)
                return;

            var fileCount = storage.Files.GetIndex(Tables.Files.Indices.Count);
            fileCount.Add(writeBatch.Value, key, key);
        }