NCBI C++ ToolKit
netcache_client_sample.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: netcache_client_sample.cpp 90014 2020-05-04 17:30:22Z ivanov $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Anatoliy Kuznetsov, David McElhany, Vladimir Ivanov, Maxim Didenko
27  *
28  *
29  */
30 
31 #include <ncbi_pch.hpp>
32 #include <corelib/ncbiapp.hpp>
33 #include <corelib/rwstream.hpp>
35 #include <util/compress/zlib.hpp>
36 
38 
39 
41 {
42 public:
43  virtual void Init(void);
44  virtual int Run(void);
45 
46 private:
47  void DemoPutRead(void);
48  void DemoPartialRead(void);
49  void DemoStream(void);
50  void DemoCompression(void);
51  void DemoIWriterIReader(void);
52 
53  string m_StreamStyle;
54 };
55 
56 
57 // Setup command line arguments and parameters
59 {
60  unique_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
61 
62  arg_desc->SetUsageContext(
63  GetArguments().GetProgramBasename(),
64  "NetCacheAPI Sample");
65 
66  arg_desc->AddOptionalKey(
67  "service",
68  "ServiceName",
69  "Load-balanced service name",
71 
72  arg_desc->AddDefaultKey(
73  "stream",
74  "StreamApi",
75  "The stream API to use",
77  "CRWStream");
78  arg_desc->SetConstraint(
79  "stream",
80  &(*new CArgAllow_Strings, "iostream", "CRWStream"),
82 
83  SetupArgDescriptions(arg_desc.release());
84 }
85 
86 
88 {
89  m_StreamStyle = GetArgs()["stream"].AsString();
90 
91  DemoPutRead();
93  DemoStream();
96 
97  return 0;
98 }
99 
100 
101 // How to perform I/O using PutData() and ReadData()
102 //
103 // Also demonstrates:
104 // configuration based on the application registry
105 // overwriting data by reusing keys
106 // controlling time-to-live
107 // getting blob info
108 
110 {
111  cout << "\nPutData()/ReadData() example:" << endl;
112 
113  // Configure based on the application registry.
115 
116  // Create a shared key to pass from writer to reader.
117  string key;
118 
119  // Write a simple object to NetCache.
120  {{
121  string message("The quick brown fox jumps over a lazy dog.");
122  key = nc_api.PutData(message.c_str(), message.size());
123  }}
124 
125  // Overwrite the data by reusing the key, and specify a time-to-live.
126  {{
127  string message("second message");
128  nc_api.PutData(key, message.c_str(), message.size(), nc_blob_ttl = 600);
129  }}
130 
131  // By not setting a time-to-live (TTL), the previously set TTL value
132  // will be replaced by the server default.
133  {{
134  string message("yet another message");
135  nc_api.PutData(key, message.c_str(), message.size());
136  cout << "Wrote: '" << message << "' to blob: " << key << endl;
137 
138  // Use GetBlobInfo() to find out what TTL the server gave this blob.
139  string blob_info;
141  while (result.ReadLine(blob_info)) {
142  if (NStr::EqualNocase(blob_info, 0, 4, "TTL:")) {
143  cout << blob_info << endl;
144  break;
145  }
146  }
147  }}
148 
149  // Read back the data for the key.
150  {{
151  string message;
152  nc_api.ReadData(key, message);
153  cout << "Read: '" << message << "'" << endl;
154  }}
155 }
156 
157 
158 // How to read just part of a large blob using PartRead()
159 //
160 // Also demonstrates:
161 // configuration based on the application registry
162 
164 {
165  cout << "\nPartRead() example:" << endl;
166 
167  // Configure based on the application registry.
169 
170  // Create a shared key to pass from writer to reader.
171  string key;
172 
173  // Write a blob to NetCache, and pretend it's really huge.
174  {{
175  string message("Just pretend this is a really huge blob, ok?");
176  key = nc_api.PutData(message.c_str(), message.size());
177  cout << "Wrote: '" << message << "' to blob: " << key << endl;
178  }}
179 
180  // Read back the data a part at a time, in case it's too big to handle
181  // all at once.
182  {{
183  // Get the full size of the blob as stored in NetCache.
184  // This is the initial size remaining to be read from NetCache.
185  size_t remaining(nc_api.GetBlobSize(key));
186 
187  // Read all parts of the blob.
188  for (size_t offset = 0; remaining > 0; ) {
189 
190  // The last read will probably be less than our max read size.
191  static const size_t kMaxReadSize = 10;
192  size_t part_size = min(remaining, kMaxReadSize);
193 
194  // Read part of the blob.
195  string part;
196  nc_api.ReadPart(key, offset, part_size, part);
197  cout << "Read: '" << part << "'" << endl;
198 
199  // Prep for the next part.
200  offset += part_size;
201  remaining -= part_size;
202  }
203  }}
204 }
205 
206 
207 // How to perform I/O using C++ iostream API -- CreateOStream() and GetIStream()
208 //
209 // Also demonstrates:
210 // configuration using a user-specified service name
211 // retrieving the same data multiple times
212 
214 {
215  cout << "\nCreateOStream()/GetIStream() example:" << endl;
216 
217  unique_ptr<CNetCacheAPI> nc_api_p;
218  {{
219  // Configure based on the user-specified service, if given.
220  if (GetArgs()["service"]) {
221  nc_api_p.reset(new CNetCacheAPI(
222  GetArgs()["service"].AsString(), "ncapi_sample"));
223  }
224  else {
225  // Default to configuring based on the application registry.
226  nc_api_p.reset(new CNetCacheAPI(GetConfig()));
227  }
228  }}
229 
230  // Create a shared key to pass from writer to reader.
231  string key;
232 
233  // Write to NetCache stream.
234  {{
235  unique_ptr<CNcbiOstream> os(nc_api_p->CreateOStream(key,
236  nc_blob_ttl = 600));
237  *os << "line one\n";
238  *os << "line two\n";
239  *os << "line three" << endl;
240  cout << "Wrote three lines to blob: " << key << endl;
241 
242  // Blobs are not finalized on the server side until the stream
243  // is deleted. So you could call os.reset() if you wanted to
244  // access the blob in the same scope as the stream unique_ptr.
245  //os.reset(); // not necessary in this example
246  }}
247 
248  // Retrieve words from NetCache stream.
249  // Note that this doesn't remove the data from NetCache.
250  {{
251  unique_ptr<CNcbiIstream> is(nc_api_p->GetIStream(key));
252  while (!is->eof()) {
253  string message;
254  *is >> message; // get one word at a time, ignoring whitespace
255  cout << "Read word: '" << message << "'" << endl;
256  }
257  }}
258 
259  // Reading from NetCache doesn't delete the data. If desired, you can
260  // retrieve the same data again by reusing the same key.
261  // In this example, get all the data at once from a NetCache stream
262  // (preserving whitespace).
263  {{
264  unique_ptr<CNcbiIstream> is(nc_api_p->GetIStream(key));
265  cout << "Read buffer: '" << is->rdbuf() << "'" << endl;
266  }}
267 }
268 
269 
270 // How to perform I/O using compression
271 //
272 // Also demonstrates:
273 // configuration based on the application registry
274 
276 {
277  cout << "\nCompression example:" << endl;
278 
279  // Configure based on the application registry.
281 
282  // Create a shared key to pass from writer to reader.
283  string key;
284 
285  // Write to NetCache with compression.
286  {{
287  string message("The quick brown fox jumps over a lazy dog.");
288  unique_ptr<CNcbiOstream> os(nc_api.CreateOStream(key));
289  CCompressionOStream os_zip(*os, new CZipStreamCompressor(),
291  os_zip << message;
292  cout << "Wrote: '" << message << "' to blob: " << key << endl;
293  }}
294 
295  // Read back from NetCache with decompression.
296  // NOTE: The decompression stream type must match the compression type.
297  {{
298  unique_ptr<CNcbiIstream> is(nc_api.GetIStream(key));
299  string message;
302  getline(is_zip, message);
303  cout << "Read: '" << message << "'" << endl;
304  }}
305 }
306 
307 
308 // How to perform I/O using IWriter() and IReader()
309 //
310 // Also demonstrates:
311 // configuration based on a provided registry
312 // reusing keys
313 
315 {
316  cout << "\nIWriter()/IReader() example:" << endl;
317 
318  // Configure based on the the provided registry. In this case it is the
319  // application registry for simplicity, but it could be any registry.
320  CNetCacheAPI nc_api(GetConfig());
321 
322  // Create a shared key to pass from writer to reader.
323  string key;
324 
325  // Write some data to NetCache. Typically this might be in a loop,
326  // but it's just done once here to cleanly illustrate the API call.
327  {{
328  // Create a data writer.
329  unique_ptr<IEmbeddedStreamWriter> writer(nc_api.PutData(&key, nc_blob_ttl = 600));
330 
331  if (m_StreamStyle == "iostream") {
332  // Write some data via ostream API.
333 
334  CWStream os(&*writer);
335  string text1("just chars."), text2("with a newline");
336  os << text1;
337  os << text2 << endl;
338  cout << "Wrote '" << text1
339  << "' and '" << text2 << "' to blob: " << key << endl;
340  } else {
341  // Write some data via IWriter API.
342 
343  char data[] = "abcdefghij1234567890!@#";
344  writer->Write(data, strlen(data)); // don't store terminating zero
345  cout << "Wrote: '" << data
346  << "' to blob: " << key << endl;
347  }
348 
349  // The blob is not committed on the server side until the
350  // writer is deleted or explicitly closed.
351  writer->Close();
352  }}
353 
354  // Read some data from NetCache. This example just demonstrates how to
355  // use the API - you can extrapolate to looping through the whole blob.
356  {{
357  // Create a data reader and get the blob size.
358  size_t blob_size;
359  unique_ptr<IReader> reader(nc_api.GetReader(key, &blob_size));
360 
361  // Don't intermix using different stream APIs. Reading via
362  // CRStream may buffer more input than you consume, possibly resulting
363  // in corrupted data and/or an exception if you switch to istream.
364 
365  if (m_StreamStyle == "iostream") {
366  // Read some data via istream API.
367 
368  CRStream is(&*reader);
369  string text1, text2;
370  is >> text1 >> text2;
371  cout << "Read '" << text1
372  << "' and '" << text2 << "' from blob:" << key << endl;
373  } else {
374  // Read some data via IReader API.
375 
376  // Create a working buffer. In this example, a zero-termination
377  // character is added only for the convenience of printing easily.
378  static const Uint8 kMyBufSize = 10;
379  char my_buf[kMyBufSize + 1];
380 
381  // Don't overflow!
382  Uint8 read_size = min<Uint8>(blob_size, kMyBufSize);
383 
384  // Note: It's possible that fewer bytes will be read than are
385  // available, without an error. Therefore, bytes_read must
386  // always be used after the read instead of read_size.
387  size_t bytes_read;
388  ERW_Result rw_res = reader->Read(my_buf, (size_t) read_size, &bytes_read);
389  my_buf[bytes_read] = '\0';
390 
391  if (rw_res == eRW_Success) {
392  cout << "Read: '" << my_buf << "'" << endl;
393  } else {
394  NCBI_USER_THROW("Error while reading blob.");
395  }
396  }
397  }}
398 }
399 
400 
401 int NcbiSys_main(int argc, ncbi::TXChar* argv[])
402 {
403  return CSampleNetCacheClient().AppMain(argc, argv);
404 }
CArgAllow_Strings –.
Definition: ncbiargs.hpp:1641
CArgDescriptions –.
Definition: ncbiargs.hpp:541
Client API for NetCache server.
Note about the "buf_size" parameter for streams in this API.
Definition: rwstream.hpp:122
virtual int Run(void)
Run the application.
virtual void Init(void)
Initialize the application.
Writer-based output stream.
Definition: rwstream.hpp:171
CZipStreamCompressor – zlib based compression stream processor.
Definition: zlib.hpp:763
CZipStreamDecompressor – zlib based decompression stream processor.
Definition: zlib.hpp:817
int offset
Definition: replacements.h:160
char data[12]
Definition: iconv.c:80
const CNcbiRegistry & GetConfig(void) const
Get the application's cached configuration parameters (read-only).
virtual const CArgs & GetArgs(void) const
Get parsed command line arguments.
Definition: ncbiapp.cpp:305
int AppMain(int argc, const char *const *argv, const char *const *envp=0, EAppDiagStream diag=eDS_Default, const char *conf=NcbiEmptyCStr, const string &name=NcbiEmptyString)
Main function (entry point) for the NCBI application.
Definition: ncbiapp.cpp:819
virtual void SetupArgDescriptions(CArgDescriptions *arg_desc)
Setup the command line argument descriptions.
Definition: ncbiapp.cpp:1195
const CNcbiArguments & GetArguments(void) const
Get the application's cached unprocessed command-line arguments.
@ eString
An arbitrary string.
Definition: ncbiargs.hpp:589
@ eConstraint
Constraint is not inverted (taken as is)
Definition: ncbiargs.hpp:924
@ fOwnReader
Delete the reader.
Definition: stream.hpp:129
@ fOwnWriter
Delete the writer.
Definition: stream.hpp:130
#define NCBI_USER_THROW(message)
Throw a quick-and-dirty runtime exception of type 'CException' with the given error message and error...
Definition: ncbiexpt.hpp:715
#define nc_blob_ttl
Blob life span in seconds.
CNcbiOstream * CreateOStream(string &key, const CNamedParameterList *optional=NULL)
Create a stream object for sending data to a blob.
size_t GetBlobSize(const string &blob_id, const CNamedParameterList *optional=NULL)
Returns the size of the BLOB identified by the "key" parameter.
void ReadPart(const string &key, size_t offset, size_t part_size, string &buffer, const CNamedParameterList *optional=NULL)
Read a part of the blob pointed to by "key" and store its contents in "buffer".
CNetServerMultilineCmdOutput GetBlobInfo(const string &blob_id, const CNamedParameterList *optional=NULL)
Return a CNetServerMultilineCmdOutput object for reading meta information about the specified blob.
string PutData(const void *buf, size_t size, const CNamedParameterList *optional=NULL)
Put BLOB to server.
CNcbiIstream * GetIStream(const string &key, size_t *blob_size=NULL, const CNamedParameterList *optional=NULL)
Create an istream object for reading blob data.
IReader * GetReader(const string &key, size_t *blob_size=NULL, const CNamedParameterList *optional=NULL)
Get a pointer to the IReader interface to read blob contents.
void ReadData(const string &key, string &buffer, const CNamedParameterList *optional=NULL)
Read the blob pointed to by "key" and store its contents in "buffer".
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
ERW_Result
Result codes for I/O operations.
@ eRW_Success
Everything is okay, I/O completed.
char TXChar
Definition: ncbistr.hpp:172
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5353
const struct ncbi::grid::netcache::search::fields::KEY key
Defines the CNcbiApplication and CAppException classes for creating NCBI applications.
NetCache client specs.
int NcbiSys_main(int argc, ncbi::TXChar *argv[])
T min(T x_, T y_)
static size_t read_size(CNcbiIstream &stream, const char *name)
Definition: reader_snp.cpp:404
Reader-writer based streams.
else result
Definition: token2.c:20
ZLib Compression API.
Modified on Wed Jun 19 17:00:21 2024 by modify_doxy.py rev. 669887