1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2#ifndef COUCHSTORE_COUCH_DB_H
3#define COUCHSTORE_COUCH_DB_H
4
5#include "couch_common.h"
6
7#include <libcouchstore/error.h>
8#include <libcouchstore/file_ops.h>
9
10#ifdef __cplusplus
11extern "C" {
12#endif
13
14    /*///////////////////  OPENING/CLOSING DATABASES: */
15
16    /*
17     * Flags to pass as the flags parameter to couchstore_open_db
18     */
19    typedef uint64_t couchstore_open_flags;
20    enum {
21        /**
22         * Create a new empty .couch file if file doesn't exist.
23         */
24        COUCHSTORE_OPEN_FLAG_CREATE = 1,
25        /**
26         * Open the database in read only mode
27         */
28        COUCHSTORE_OPEN_FLAG_RDONLY = 2,
29        /**
30         * Require the database to use the legacy CRC.
31         * This forces the disk_version flag to be 11 and is only valid for new files
32         * and existing version 11 files.
33         * When excluded the correct CRC is automatically chosen for existing files.
34         * When excluded the latest file version is always used for new files.
35         */
36        COUCHSTORE_OPEN_WITH_LEGACY_CRC = 4,
37        /**
38         * Open the database file without using an IO buffer
39         *
40         * This prevents the FileOps that are used in from being
41         * wrapped by the buffered file operations. This will
42         * *usually* result in performance degradation and is
43         * primarily intended for testing purposes.
44         */
45        COUCHSTORE_OPEN_FLAG_UNBUFFERED = 8,
46        /**
47         * Customize IO buffer configurations.
48         *
49         * This specifies the capacity of a read buffer and its count.
50         * The first 4 bits are for the capacity, that will be calculated as:
51         *     1KB * 1 << (N-1)
52         * And the next 4 bits are for the count:
53         *     8 * 1 << (N-1)
54         * Note that all zeros represent the default setting.
55         */
56        COUCHSTORE_OPEN_WITH_CUSTOM_BUFFER = 0xff00,
57        /**
58         * Customize B+tree node size.
59         *
60         * This specifies the size of B+tree node.
61         * The first 4 bits represents the size of key-pointer
62         * (i.e., intermediate) nodes in KB, and the next 4 bits denotes
63         * the size of key-value (i.e., leaf) nodes in KB.
64         * Note that all zeros represent the default setting,
65         * 1279 (0x4ff) bytes.
66         */
67        COUCHSTORE_OPEN_WITH_CUSTOM_NODESIZE = 0xff0000,
68
69        /**
70         * Enable periodic sync().
71         *
72         * Automatically perform a sync() call after every N bytes written.
73         *
74         * When writing large amounts of data (e.g during compaction), read
75         * latency can be adversely affected if a single sync() is made at the
76         * end of writing all the data; as the IO subsystem has a large amount
77         * of outstanding writes to flush to disk. By issuing periodic syncs
78         * the affect on read latency can be signifcantly reduced.
79         *
80         * Encoded as a power-of-2 KB value, ranging from 1KB .. 1TB (5 bits):
81         *     1KB * << (N-1)
82         *
83         * A value of N=0 specifies that automatic fsync is disabled.
84         */
85        COUCHSTORE_OPEN_WITH_PERIODIC_SYNC = 0x1f000000,
86    };
87
88    /**
89     * Encode a periodic sync specified in bytes to the correct
90     * couchstore_open_flags encoding.
91     * @param fsync period in bytes
92     * @return encoded open_flags value, ranging from 1KB to 1TB. Rounded down
93     *         to nearest power-of-2.
94     */
95    LIBCOUCHSTORE_API
96    couchstore_open_flags couchstore_encode_periodic_sync_flags(uint64_t bytes);
97
98    /**
99     * Open a database.
100     *
101     * The database should be closed with couchstore_close_db().
102     *
103     * @param filename The name of the file containing the database
104     * @param flags Additional flags for how the database should
105     *              be opened. See couchstore_open_flags_* for the
106     *              available flags.
107     * @param db Pointer to where you want the handle to the database to be
108     *           stored.
109     * @return COUCHSTORE_SUCCESS for success
110     */
111    LIBCOUCHSTORE_API
112    couchstore_error_t couchstore_open_db(const char *filename,
113                                          couchstore_open_flags flags,
114                                          Db **db);
115
116    /**
117     * Open a database, with custom I/O callbacks.
118     *
119     * The database should be closed with couchstore_close_db().
120     *
121     * @param filename The name of the file containing the database
122     * @param flags Additional flags for how the database should
123     *              be opened. See couchstore_open_flags_* for the
124     *              available flags.
125     * @param ops Pointer to the implementation of FileOpsInterface
126     *            you want the library to use.
127     * @param db Pointer to where you want the handle to the database to be
128     *           stored.
129     * @return COUCHSTORE_SUCCESS for success
130     */
131    LIBCOUCHSTORE_API
132    couchstore_error_t couchstore_open_db_ex(const char *filename,
133                                             couchstore_open_flags flags,
134                                             FileOpsInterface* ops,
135                                             Db **db);
136
137    /**
138     * Release all resources held by the database handle after the file
139     * has been closed.
140     *
141     * This should be called *after* couchstore_close_file(db).
142     *
143     * @param db Pointer to the database handle to free.
144     * @return COUCHSTORE_SUCCESS upon success
145     */
146    LIBCOUCHSTORE_API
147    couchstore_error_t couchstore_free_db(Db* db);
148
149
150    /**
151     * Close the file handle associated with this database handle.
152     *
153     * This does not free the resources held by the database handle. These
154     * resources should be released by subsequently calling
155     * couchstore_free_db(db).
156     *
157     * @param db Pointer to the database handle to drop the file from.
158     * @return COUCHSTORE_SUCCESS upon success
159     */
160    LIBCOUCHSTORE_API
161    couchstore_error_t couchstore_close_file(Db* db);
162
163    /**
164     * Rewind a db handle to the next-oldest header still present in the file.
165     * If there is no next-oldest header, the db handle will be *closed*, and
166     * COUCHSTORE_DB_NO_LONGER_VALID will be returned.
167     *
168     * @param db The database handle to rewind
169     * @return COUCHSTORE_SUCCESS upon success, COUCHSTORE_DB_NO_LONGER_VALID if
170     * no next-oldest header was found.
171     */
172    LIBCOUCHSTORE_API
173    couchstore_error_t couchstore_rewind_db_header(Db *db);
174
175    /**
176     * Get the default FileOpsInterface object
177     */
178    LIBCOUCHSTORE_API
179    FileOpsInterface* couchstore_get_default_file_ops(void);
180
181    /**
182     * Get information about the database.
183     *
184     * @param db Pointer to the database handle.
185     * @param info Pointer to where you want the info to be stored.
186     * @return COUCHSTORE_SUCCESS upon success
187     */
188    LIBCOUCHSTORE_API
189    couchstore_error_t couchstore_db_info(Db *db, DbInfo* info);
190
191
192    /**
193     * Returns the filename of the database, as given when it was opened.
194     *
195     * @param db Pointer to the database handle.
196     * @return Pointer to filename (path). This is an exact copy of the filename given to
197     *         couchstore_open_db.
198     */
199    LIBCOUCHSTORE_API
200    const char* couchstore_get_db_filename(Db *db);
201
202#ifdef __cplusplus
203    /**
204     * Return file handle statistics of the database's underlying file handle.
205     *
206     * @return A non-null pointer to a FileStats instance if the
207     *         database's file ops support file statistics, otherwise
208     *         returns nullptr.
209     */
210    LIBCOUCHSTORE_API
211    FileOpsInterface::FHStats* couchstore_get_db_filestats(Db* db);
212#endif
213
214    /**
215     * Get the position in the file of the mostly recently written
216     * database header.
217     */
218    LIBCOUCHSTORE_API
219    uint64_t couchstore_get_header_position(Db *db);
220
221
222    /*////////////////////  WRITING DOCUMENTS: */
223
224    /*
225     * Options used by couchstore_save_document() and
226     * couchstore_save_documents():
227     */
228    typedef uint64_t couchstore_save_options;
229    enum {
230        /**
231         * Snappy compress document data if the high bit of the
232         * content_meta field of the DocInfo is set. This is NOT the
233         * default, and if this is not set the data field of the Doc will
234         * be written to disk as-is, regardless of the content_meta flags.
235         */
236        COMPRESS_DOC_BODIES = 1,
237        /**
238         * Store the DocInfo's passed in db_seq as is.
239         *
240         * Couchstore will *not* assign it a new sequence number, but store the
241         * sequence number as given. The update_seq for the DB will be set to
242         * at least this sequence.
243         * */
244        COUCHSTORE_SEQUENCE_AS_IS = 2
245    };
246
247    /**
248     * Save document pointed to by doc and docinfo to db.
249     *
250     * When saving documents you should only set the id, rev_meta,
251     * rev_seq, deleted, and content_meta fields on the DocInfo.
252     *
253     * To delete a docuemnt, set doc to NULL.
254     *
255     * On return, the db_seq field of the DocInfo will be filled in with the
256     * document's (or deletion's) sequence number.
257     *
258     * @param db database to save the document in
259     * @param doc the document to save
260     * @param info document info
261     * @param options see descrtiption of COMPRESS_DOC_BODIES below
262     * @return COUCHSTORE_SUCCESS upon success
263     */
264    LIBCOUCHSTORE_API
265    couchstore_error_t couchstore_save_document(Db *db,
266                                                const Doc *doc,
267                                                DocInfo *info,
268                                                couchstore_save_options options);
269
270    /**
271     * Save array of docs to db
272     *
273     * To delete documents, set docs to NULL: the docs referenced by
274     * the docinfos will be deleted. To intermix deletes and inserts
275     * in a bulk update, pass docinfos with the deleted flag set.
276     *
277     * On return, the db_seq fields of the DocInfos will be filled in with the
278     * documents' (or deletions') sequence numbers.
279     *
280     * @param db the database to save documents in
281     * @param docs an array of document pointers
282     * @param infos an array of docinfo pointers
283     * @param numDocs the number documents to save
284     * @param options see descrtiption of COMPRESS_DOC_BODIES below
285     * @return COUCHSTORE_SUCCESS upon success
286     */
287    LIBCOUCHSTORE_API
288    couchstore_error_t couchstore_save_documents(Db *db,
289                                                 Doc* const docs[],
290                                                 DocInfo *infos[],
291                                                 unsigned numDocs,
292                                                 couchstore_save_options options);
293    /**
294     * Commit all pending changes and flush buffers to persistent storage.
295     *
296     * @param db database to perform the commit on
297     * @return COUCHSTORE_SUCCESS on success
298     */
299    LIBCOUCHSTORE_API
300    couchstore_error_t couchstore_commit(Db *db);
301
302
303    /*////////////////////  RETRIEVING DOCUMENTS: */
304
305    /**
306     * Retrieve the document info for a given key.
307     *
308     * The info should be freed with couchstore_free_docinfo().
309     *
310     * @param id the document identifier
311     * @param idlen the number of bytes in the identifier
312     * @param pInfo where to store the result
313     * @return COUCHSTORE_SUCCESS on success.
314     */
315    LIBCOUCHSTORE_API
316    couchstore_error_t couchstore_docinfo_by_id(Db *db,
317                                                const void *id,
318                                                size_t idlen,
319                                                DocInfo **pInfo);
320
321    /**
322     * Retrieve the document info for a given sequence number.
323     *
324     * To look up multiple sequences, it's more efficient to call couchstore_docinfos_by_sequence.
325     *
326     * @param sequence the document sequence number
327     * @param pInfo where to store the result. Must be freed with couchstore_free_docinfo().
328     * @return COUCHSTORE_SUCCESS on success.
329     */
330    LIBCOUCHSTORE_API
331    couchstore_error_t couchstore_docinfo_by_sequence(Db *db,
332                                                      uint64_t sequence,
333                                                      DocInfo **pInfo);
334
335    /** Options flags for open_doc and open_doc_with_docinfo */
336    typedef uint64_t couchstore_open_options;
337    enum {
338        /* Snappy decompress document data if the high bit of the content_meta field
339         * of the DocInfo is set.
340         * This is NOT the default, and if this is not set the data field of the Doc
341         * will be read from disk as-is, regardless of the content_meta flags. */
342        DECOMPRESS_DOC_BODIES = 1
343    };
344
345    /**
346     * Retrieve a doc from the db.
347     *
348     * The document should be freed with couchstore_free_document()
349     *
350     * On a successful return, doc.id.buf will point to the id you passed in,
351     * so don't free or overwrite the id buffer before freeing the document!
352     *
353     * @param db database to load document from
354     * @param id the identifier to load
355     * @param idlen the number of bytes in the id
356     * @param pDoc Where to store the result
357     * @param options See DECOMPRESS_DOC_BODIES
358     * @return COUCHSTORE_SUCCESS if found
359     */
360    LIBCOUCHSTORE_API
361    couchstore_error_t couchstore_open_document(Db *db,
362                                                const void *id,
363                                                size_t idlen,
364                                                Doc **pDoc,
365                                                couchstore_open_options options);
366
367    /**
368     * Retrieve a doc from the db, using a DocInfo.
369     * The DocInfo must have been filled in with valid values by an API call such
370     * as couchstore_docinfo_by_id().
371     *
372     * Do not free the docinfo before freeing the doc, with couchstore_free_document().
373     *
374     * @param db database to load document from
375     * @param docinfo a valid DocInfo, as filled in by couchstore_docinfo_by_id()
376     * @param pDoc Where to store the result
377     * @param options See DECOMPRESS_DOC_BODIES
378     * @return COUCHSTORE_SUCCESS if found
379     */
380    LIBCOUCHSTORE_API
381    couchstore_error_t couchstore_open_doc_with_docinfo(Db *db,
382                                                        const DocInfo *docinfo,
383                                                        Doc **pDoc,
384                                                        couchstore_open_options options);
385
386    /**
387     * Free all allocated resources from a document returned from
388     * couchstore_open_document().
389     *
390     * @param doc the document to free. May be NULL.
391     */
392    LIBCOUCHSTORE_API
393    void couchstore_free_document(Doc *doc);
394
395
396    /**
397     * Allocates a new DocInfo structure on the heap, plus optionally its id and rev_meta.
398     * If the id or rev_meta are given, their values will be copied into the allocated memory
399     * and the corresponding fields in the returned DocInfo will point there. Otherwise the
400     * DocInfo's id and/or rev_meta fields will be empty/null.
401     * @param id the document ID to copy into the DocInfo, or NULL to leave its ID NULL.
402     * @param rev_meta the revision metadata to copy into the DocInfo, or NULL to leave its
403     *          rev_meta NULL.
404     * @return the allocated DocInfo, or NULL on an allocation failure. Must be freed by
405     *          calling couchstore_free_docinfo.
406     */
407    LIBCOUCHSTORE_API
408    DocInfo* couchstore_alloc_docinfo(const sized_buf *id,
409                                      const sized_buf *rev_meta);
410
411
412    /**
413     * Free all allocated resources from a docinfo structure returned by
414     * couchstore_docinfo_by_id() or passed to a couchstore_changes_callback_fn.
415     *
416     * @param docinfo the document info to free. May be NULL.
417     */
418    LIBCOUCHSTORE_API
419    void couchstore_free_docinfo(DocInfo *docinfo);
420
421
422    /*////////////////////  ITERATING DOCUMENTS: */
423
424    /**
425     * The callback function used by couchstore_changes_since(), couchstore_docinfos_by_id()
426     * and couchstore_docinfos_by_sequence() to iterate through the documents.
427     *
428     * The docinfo structure is automatically freed if the callback
429     * returns 0. A positive return value will preserve the DocInfo
430     * for future use (should be freed with free_docinfo by the
431     * caller). A negative return value will cancel the iteration and
432     * pass the error value back to the caller.
433     *
434     * @param db the database being traversed
435     * @param docinfo the current document
436     * @param ctx user context
437     * @return 1 to preserve the DocInfo, 0 or negative error value to free it (see above).
438     */
439    typedef int (*couchstore_changes_callback_fn)(Db *db,
440                                                  DocInfo *docinfo,
441                                                  void *ctx);
442
443    /** Options flags for document iteration */
444    typedef uint64_t couchstore_docinfos_options;
445    enum {
446        /* If set, the sequences/ids lists are interpreted as pairs of range endpoints,
447         * and all documents within those ranges will be iterated over.
448         */
449        RANGES = 1,
450        /**
451         * Send only deleted items.
452         */
453        COUCHSTORE_DELETES_ONLY = 2,
454        /**
455         * Send only non-deleted items.
456         */
457        COUCHSTORE_NO_DELETES = 4,
458        /**
459         * If set, corrupted B+tree nodes or documents will be tolerated
460         * to collect as much data as possible.
461         */
462        COUCHSTORE_TOLERATE_CORRUPTION = 8
463    };
464
465    /**
466     * Iterate through the changes since sequence number `since`.
467     *
468     * @param db the database to iterate through
469     * @param since the sequence number to start iterating from
470     * @param options COUCHSTORE_DELETES_ONLY and COUCHSTORE_NO_DELETES are supported
471     * @param callback the callback function used to iterate over all changes
472     * @param ctx client context (passed to the callback)
473     * @return COUCHSTORE_SUCCESS upon success
474     */
475    LIBCOUCHSTORE_API
476    couchstore_error_t couchstore_changes_since(Db *db,
477                                                uint64_t since,
478                                                couchstore_docinfos_options options,
479                                                couchstore_changes_callback_fn callback,
480                                                void *ctx);
481
482    /**
483     * Iterate through all documents in order by key.
484     *
485     * @param db the database to iterate through
486     * @param startKeyPtr  The key to start at, or NULL to start from the beginning
487     * @param options COUCHSTORE_DELETES_ONLY and COUCHSTORE_NO_DELETES are supported
488     * @param callback the callback function used to iterate over all documents
489     * @param ctx client context (passed to the callback)
490     * @return COUCHSTORE_SUCCESS upon success
491     */
492    LIBCOUCHSTORE_API
493    couchstore_error_t couchstore_all_docs(Db *db,
494                                           const sized_buf* startKeyPtr,
495                                           couchstore_docinfos_options options,
496                                           couchstore_changes_callback_fn callback,
497                                           void *ctx);
498
499    /**
500     * Iterate over the document infos of a set of sequence numbers.
501     *
502     * The DocInfos will be presented to the callback in order of ascending sequence
503     * number, *not* in the order in which they appear in the sequence[] array.
504     *
505     * If the RANGES option flag is set, the sequences array is interpreted as
506     * alternating begin/end points of ranges, and all DocInfos within those ranges
507     * are iterated over. (If there is an odd number of sequences, the iteration will
508     * stop at the last sequence.)
509     *
510     * The callback will not be invoked for nonexistent sequence numbers.
511     *
512     * @param sequence array of document sequence numbers. Need not be sorted but must not contain
513     *          duplicates.
514     * @param numDocs number of documents to look up (size of sequence[] array)
515     * @param options Set the RANGES bit for range mode (see above)
516     * @param callback the callback function used to iterate over document infos
517     * @param ctx client context (passed to the callback)
518     * @return COUCHSTORE_SUCCESS on success.
519     */
520    LIBCOUCHSTORE_API
521    couchstore_error_t couchstore_docinfos_by_sequence(Db *db,
522                                                       const uint64_t sequence[],
523                                                       unsigned numDocs,
524                                                       couchstore_docinfos_options options,
525                                                       couchstore_changes_callback_fn callback,
526                                                       void *ctx);
527
528    /**
529     * Iterate over the document infos of a set of ids.
530     *
531     * The DocInfos will be presented to the callback in order of ascending document id,
532     * *not* in the order in which they appear in the ids[] array.
533     *
534     * If the RANGES option flag is set, the ids array is interpreted as alternating
535     * begin/end points of ranges, and all DocInfos with IDs within those ranges
536     * are iterated over. (If there is an odd number of IDs, the iteration will
537     * stop at the last ID.)
538     *
539     * The callback will not be invoked for nonexistent ids.
540     *
541     * @param ids array of document ids. Need not be sorted but must not contain
542     *          duplicates.
543     * @param numDocs number of documents to look up (size of ids[] array)
544     * @param options Set the RANGES bit for range mode (see above)
545     * @param callback the callback function used to iterate over document infos
546     * @param ctx client context (passed to the callback)
547     * @return COUCHSTORE_SUCCESS on success.
548     */
549    LIBCOUCHSTORE_API
550    couchstore_error_t couchstore_docinfos_by_id(Db *db,
551                                                 const sized_buf ids[],
552                                                 unsigned numDocs,
553                                                 couchstore_docinfos_options options,
554                                                 couchstore_changes_callback_fn callback,
555                                                 void *ctx);
556
557    /*////////////////////  ITERATING TREES: */
558
559    /**
560     * The callback function used by couchstore_walk_id_tree() and couchstore_walk_seq_tree()
561     * to iterate through the B-tree.
562     *
563     * This function is called both for documents and tree nodes. reduce_value will be non-NULL
564     * for a node; doc_info will be non-NULL for a document.
565     *
566     * The docinfo structure is automatically freed if the callback
567     * returns 0. A positive return value will preserve the DocInfo
568     * for future use (should be freed with free_docinfo by the
569     * caller). A negative return value will cancel the iteration and
570     * pass the error value back to the caller.
571     *
572     * @param db the database being traversed
573     * @param depth the current depth in the tree (the root node is 0, and documents are one level
574     *          deeper than their leaf nodes)
575     * @param doc_info the current document, or NULL if this is a tree node
576     * @param subtree_size the on-disk size of this tree node and its children, or 0 for a document
577     * @param reduce_value the reduce data of this node, or NULL for a document
578     * @param ctx user context
579     * @return 1 to preserve the DocInfo, 0 to free it, or a negative error code to abort iteration.
580     */
581    typedef int (*couchstore_walk_tree_callback_fn)(Db *db,
582                                                    int depth,
583                                                    const DocInfo* doc_info,
584                                                    uint64_t subtree_size,
585                                                    const sized_buf* reduce_value,
586                                                    void *ctx);
587
588    /**
589     * Iterate through the by-ID B-tree, including interior and leaf nodes as well as documents.
590     *
591     * The iteration is depth-first, in order by document ID. The callback is invoked on a tree
592     * node before its children. The first call is for the root node.
593     *
594     * This is only useful for tools that want to examine the B-tree structure or reduced values,
595     * such as couch_dbdump. It's unlikely that applications will need to use it.
596     *
597     * @param db the database to iterate through
598     * @param startDocID  The key to start at, or NULL to start from the beginning
599     * @param options COUCHSTORE_DELETES_ONLY and COUCHSTORE_NO_DELETES are supported
600     * @param callback the callback function used to iterate over all documents
601     * @param ctx client context (passed to the callback)
602     * @return COUCHSTORE_SUCCESS upon success
603     */
604    LIBCOUCHSTORE_API
605    couchstore_error_t couchstore_walk_id_tree(Db *db,
606                                               const sized_buf* startDocID,
607                                               couchstore_docinfos_options options,
608                                               couchstore_walk_tree_callback_fn callback,
609                                               void *ctx);
610
611    /**
612     * Iterate through the by-sequence B-tree, including interior and leaf nodes as well as documents.
613     *
614     * The iteration is depth-first, in order by sequence. The callback is invoked on a tree
615     * node before its children. The first call is for the root node.
616     *
617     * This is only useful for tools that want to examine the B-tree structure or reduced values,
618     * such as couch_dbdump. It's unlikely that applications will need to use it.
619     *
620     * @param db the database to iterate through
621     * @param startSequence the sequence number to start from
622     * @param options COUCHSTORE_DELETES_ONLY and COUCHSTORE_NO_DELETES are supported
623     * @param callback the callback function used to iterate over all documents
624     * @param ctx client context (passed to the callback)
625     * @return COUCHSTORE_SUCCESS upon success
626     */
627    LIBCOUCHSTORE_API
628    couchstore_error_t couchstore_walk_seq_tree(Db *db,
629                                                uint64_t startSequence,
630                                                couchstore_docinfos_options options,
631                                                couchstore_walk_tree_callback_fn callback,
632                                                void *ctx);
633
634    /*////////////////////  LOCAL DOCUMENTS: */
635
636    /**
637     * Get a local doc from the db.
638     *
639     * The document should be freed with couchstore_free_local_document().
640     *
641     * @param db database to load document from
642     * @param id the identifier to load (must begin with "_local/")
643     * @param idlen the number of bytes in the id
644     * @param lDoc Where to store the result
645     * @return COUCHSTORE_SUCCESS if found
646     */
647    LIBCOUCHSTORE_API
648    couchstore_error_t couchstore_open_local_document(Db *db,
649                                                      const void *id,
650                                                      size_t idlen,
651                                                      LocalDoc **lDoc);
652
653    /**
654     * Save a local doc to the db. Its identifier must begin with "_local/".
655     * To delete an existing doc, set the deleted flag on the LocalDoc
656     * struct. The json buffer will be ignored for a deletion.
657     *
658     * @param db the database to store the document in
659     * @param lDoc the document to store
660     * @return COUCHSTORE_SUCCESS on success
661     */
662    LIBCOUCHSTORE_API
663    couchstore_error_t couchstore_save_local_document(Db *db, LocalDoc *lDoc);
664
665    /*
666     * Free all allocated resources from a LocalDoc obtained from
667     * couchstore_open_local_document().
668     *
669     * @param lDoc document to free
670     */
671    LIBCOUCHSTORE_API
672    void couchstore_free_local_document(LocalDoc *lDoc);
673
674
675    /*////////////////////  UTILITIES: */
676
677    /**
678     * Compact a database. This creates a new DB file with the same data as the
679     * source db, omitting data that is no longer needed.
680     * Will use default couch_file_ops to create and write the target db.
681     *
682     * @param source the source database
683     * @param target_filename the filename of the new database to create.
684     * @return COUCHSTORE_SUCCESS on success
685     */
686    LIBCOUCHSTORE_API
687    couchstore_error_t couchstore_compact_db(Db* source, const char* target_filename);
688
689
690    /*
691     * Flags to pass as the flags parameter to couchstore_compact_db_ex
692     */
693    typedef uint64_t couchstore_compact_flags;
694    enum {
695        /**
696         * Do not copy the tombstones of deleted items into compacted file.
697         */
698        COUCHSTORE_COMPACT_FLAG_DROP_DELETES = 1,
699
700        /**
701         * Upgrade the database whilst compacting.
702         * The only supported upgrade is from version 11 to 12 which
703         * changes the CRC function used.
704         */
705        COUCHSTORE_COMPACT_FLAG_UPGRADE_DB = 2,
706
707        /**
708         * Open the target database file without using an IO buffer
709         *
710         * This prevents the FileOps that are used in from being
711         * wrapped by the buffered file operations. This will
712         * *usually* result in performance degradation and is
713         * primarily intended for testing purposes.
714         */
715        COUCHSTORE_COMPACT_FLAG_UNBUFFERED = 4,
716
717        /**
718         * This flag internally turns on 'error toleration' mode,
719         * so as to migrate as many KV pairs as possible to the new
720         * file, without aborting the task in the middle of compaction.
721         */
722        COUCHSTORE_COMPACT_RECOVERY_MODE = 8,
723
724        /**
725         * Currently unused flag bits.
726         */
727        COUCHSTORE_COMPACT_UNUSED = 0xfffff0,
728
729        /**
730         * Enable periodic sync().
731         *
732         * Automatically perform a sync() call after every N bytes written.
733         * Same encoding as COUCHSTORE_OPEN_WITH_PERIODIC_SYNC - see
734         * couchstore_open_flags for details.
735         */
736        COUCHSTORE_COMPACT_WITH_PERIODIC_SYNC = 0x1f000000,
737    };
738
739    /**
740     * A compactor hook will be given each DocInfo, and can either keep or drop the item
741     * based on its contents.
742     *
743     * It can also return a couchstore error code, which will abort the compaction.
744     *
745     * If a compactor hook is set, COUCHSTORE_COMPACT_FLAG_DROP_DELETES will *not* drop deletes,
746     * but will bump the purge counter. The hook is responsible for dropping deletes.
747     *
748     * The couchstore_docinfo_hook is for editing the docinfo of the item if the rev_meta
749     * section in docinfo is not found to already contain extended metadata.
750     */
751    enum {
752        COUCHSTORE_COMPACT_KEEP_ITEM = 0,
753        COUCHSTORE_COMPACT_DROP_ITEM = 1,
754        // The compact hook might need to see the full body to determine
755        // if it should keep or drop the body. By default the body is
756        // _not_ being read (as we expect that "keep" would be the common
757        // path).
758        COUCHSTORE_COMPACT_NEED_BODY = 2
759    };
760
761    typedef int (*couchstore_compact_hook)(Db* target,
762                                           DocInfo *docinfo,
763                                           sized_buf item, // is {nullptr, 0}
764                                           void *ctx);
765
766    typedef int (*couchstore_docinfo_hook)(DocInfo **docinfo,
767                                           const sized_buf *item);
768
769    /**
770     * Set purge sequence number. This allows the compactor hook to set the highest
771     * purged sequence number into the header once compaction is complete
772     *
773     * @param target any database whose's purge_seq needs to be set
774     * @param purge_seq the sequence number to set into the header's purge_seq.
775     * @return COUCHSTORE_SUCCESS on success
776     */
777    LIBCOUCHSTORE_API
778    couchstore_error_t couchstore_set_purge_seq(Db* target, uint64_t purge_seq);
779
780    /**
781     * Compact a database. This creates a new DB file with the same data as the
782     * source db, omitting data that is no longer needed.
783     * Will use specified couch_file_ops to create and write the target db.
784     *
785     * @param source the source database
786     * @param target_filename the filename of the new database to create.
787     * @param flags flags that change compaction behavior
788     * @param hook time_purge_hook callback
789     * @param dhook get_extmeta_hook callback
790     * @param hook_ctx compaction_ctx struct
791     * @param ops Pointer to the FileOpsInterface implementation
792     *            you want the library to use.
793     * @return COUCHSTORE_SUCCESS on success
794     */
795    LIBCOUCHSTORE_API
796    couchstore_error_t couchstore_compact_db_ex(Db* source, const char* target_filename, uint64_t flags,
797                                                couchstore_compact_hook hook,
798                                                couchstore_docinfo_hook dhook, void* hook_ctx,
799                                                FileOpsInterface* ops);
800
801
802    /*////////////////////  MISC: */
803
804    /**
805     * Convert an error code from couchstore to a textual description. The
806     * text is a constant within the library so you should not try to modify
807     * or free the pointer.
808     *
809     * @param errcode The error code to look up
810     * @return a textual description of the error
811     */
812    LIBCOUCHSTORE_API
813    const char *couchstore_strerror(couchstore_error_t errcode);
814
815    /**
816     * Prints a description of the last OS-level errors that Couchstore
817     * encountered on this thread into buf.
818     *
819     * @param buf The buffer to store the message in
820     * @param size The size of the buffer.
821     */
822     LIBCOUCHSTORE_API
823     couchstore_error_t couchstore_last_os_error(const Db *db,
824                                                 char* buf,
825                                                 size_t size);
826
827     /**
828      * Counts the number of changes between two sequence numbers, inclusive.
829      *
830      * @param db The db to count changes in
831      * @param min_seq The minimum sequence to count
832      * @param max_seq The maximum sequence to count
833      * @param count Pointer to uint64_t to store count in
834      * @return COUCHSTORE_SUCCESS on success
835      */
836     LIBCOUCHSTORE_API
837     couchstore_error_t couchstore_changes_count(Db* db,
838                                                 uint64_t min_seq,
839                                                 uint64_t max_seq,
840                                                 uint64_t *count);
841
842#ifdef __cplusplus
843}
844#endif
845#endif
846