using System.Collections.ObjectModel; using System.Text; using FrostFS.SDK; using FrostFS.SDK.Client; using FrostFS.SDK.Client.Interfaces; using Grpc.Core; using Grpc.Net.Client; using Microsoft.Extensions.Options; class Tools { public static IFrostFSClient CreateClient(string key, string host) { var clientOptions = Options.Create(new ClientSettings { Key = key, Host = host }); Func grpcChannel = (url) => GrpcChannel.ForAddress(new Uri(url)); var client = FrostFSClient.GetInstance(clientOptions, grpcChannel); return client; } #region Session public static async Task GetSessionTokenAsync(IFrostFSClient client) { return await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue), default); } #endregion #region Chain public static async Task> AddContainerChainRuleAsync(IFrostFSClient client, FrostFsContainerId containerId, string chainId, string[] actions) { var addChainPrm = new PrmApeChainAdd( new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()), new FrostFsChain { ID = Encoding.ASCII.GetBytes(chainId), Rules = [ new FrostFsRule { Status = RuleStatus.Allow, Actions = new Actions(inverted: false, names: actions), Resources = new Resource (inverted: false, names: [$"native:object/*"]), Any = false, Conditions = [] } ], MatchType = RuleMatchType.DenyPriority } ); var result = await client.AddChainAsync(addChainPrm, default); await Task.Delay(8000); return result; } public static async Task RemoveContainerChainAsync(IFrostFSClient client, FrostFsContainerId containerId, string chainId) { var target = new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()); var args = new PrmApeChainRemove(target, Encoding.ASCII.GetBytes(chainId)); await client.RemoveChainAsync(args, default); } // TODO: implement deserializer public static async Task ListContainerChainAsync(IFrostFSClient client, FrostFsContainerId containerId) { var target = new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()); var args = new PrmApeChainList(target); var list = await client.ListChainAsync(args, default); return [.. list.Select(c => c.Raw.ToByteArray())]; } #endregion #region Container public static async Task CreateContainerAsync(IFrostFSClient client, FrostFsAttributePair[] attributes) { var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), attributes), PrmWait.DefaultParams); return await client.CreateContainerAsync(createContainerParam, default); } public static async Task DeleteContainerAsync(IFrostFSClient client, FrostFsContainerId containerId) { var args = new PrmContainerDelete(containerId, new PrmWait(60, 5)); await client.DeleteContainerAsync(args, default); } public static async Task> ListContainersAsync(IFrostFSClient client, FrostFsContainerId containerId) { var args = new PrmContainerGetAll(); Collection containers = []; await foreach (var cid in client.ListContainersAsync(args, default)) { containers.Add(cid); } return containers; } public static async Task Cleanup(IFrostFSClient client) { await foreach (var cid in client.ListContainersAsync(default, default)) { await client.DeleteContainerAsync(new PrmContainerDelete(cid, PrmWait.DefaultParams), default); } } #endregion #region Object public static async Task GetObjectHeadAsync(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId) { var args = new PrmObjectHeadGet(containerId, objectId); return await client.GetObjectHeadAsync(args, default); } public static async Task GetObjectAsync(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId) { var args = new PrmObjectGet(containerId, objectId); return await client.GetObjectAsync(args, default); } public static async Task GetRangeAsync(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId) { var args = new PrmRangeGet(containerId, objectId, new FrostFsRange(64, 128)); var rangeReader = await client.GetRangeAsync(args, default); var downloadedBytes = new byte[128]; MemoryStream ms = new(downloadedBytes); ReadOnlyMemory? chunk; while ((chunk = await rangeReader!.ReadChunk()) != null) { ms.Write(chunk.Value.Span); } return downloadedBytes; } public static async Task[]> GetRangeHashAsync(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId) { Random rnd = new(); var salt = new byte[32]; rnd.NextBytes(salt); var args = new PrmRangeHashGet(containerId, objectId, [new FrostFsRange(100, 64)], salt); return await client.GetRangeHashAsync(args, default); } public static async Task PutObjectAsync(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes) { var args = new PrmObjectPut( new FrostFsObjectHeader( containerId: containerId, type: FrostFsObjectType.Regular, [new FrostFsAttributePair("fileName", "test")])); var stream = await client.PutObjectAsync(args, default); await stream.WriteAsync(bytes.AsMemory()); var objectId = await stream.CompleteAsync(); return objectId; } public static async Task PutSingleObjectAsync(IFrostFSClient client, FrostFsContainerId container, byte[] bytes) { var header = new FrostFsObjectHeader( containerId: container, type: FrostFsObjectType.Regular, attributes: null, split: null, owner: null, version: null); var obj = new FrostFsObject(header); var args = new PrmSingleObjectPut(obj); return await client.PutSingleObjectAsync(args, default); } public static async Task PatchObjectAsync(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId, byte[] patch) { var range = new FrostFsRange(64, (ulong)patch.Length); var args = new PrmObjectPatch( new FrostFsAddress(containerId, objectId), payload: new MemoryStream(patch), maxChunkLength: 256, range: range); return await client.PatchObjectAsync(args, default); } public static async Task DeleteObjectAsync(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId, byte[] patch) { var args = new PrmObjectDelete(containerId, objectId); await client.DeleteObjectAsync(args, default); } public static async Task> SearchObjectsAsync(IFrostFSClient client, FrostFsContainerId containerId) { var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test"); var args = new PrmObjectSearch(containerId, null, [], filter); Collection objects = []; await foreach (var objId in client.SearchObjectsAsync(args, default)) { objects.Add(objId); } return objects; } #endregion }