File: index-api.html

package info (click to toggle)
cyrus-imapd 3.12.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 60,760 kB
  • sloc: ansic: 280,403; perl: 146,834; javascript: 9,624; sh: 5,730; yacc: 2,660; cpp: 2,263; makefile: 2,103; lex: 675; xml: 621; awk: 303; python: 273; asm: 262
file content (208 lines) | stat: -rw-r--r-- 12,764 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
  <meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Index API &mdash; Cyrus IMAP 3.12.1 documentation</title>
      <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
      <link rel="stylesheet" href="../../../_static/css/theme.css" type="text/css" />
      <link rel="stylesheet" href="../../../_static/graphviz.css" type="text/css" />
      <link rel="stylesheet" href="../../../_static/cyrus.css" type="text/css" />
  
        <script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
        <script src="../../../_static/jquery.js"></script>
        <script src="../../../_static/underscore.js"></script>
        <script src="../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
        <script src="../../../_static/doctools.js"></script>
        <script src="../../../_static/sphinx_highlight.js"></script>
    <script src="../../../_static/js/theme.js"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />
    <link rel="next" title="Mailbox API" href="mailbox-api.html" />
    <link rel="prev" title="cyrusdb API" href="cyrusdb2.html" /> 
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >

          
          
          <a href="../../../index.html" class="icon icon-home">
            Cyrus IMAP
          </a>
              <div class="version">
                3.12.1
              </div>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
              <p class="caption" role="heading"><span class="caption-text">Cyrus IMAP</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../../download.html">Download</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../quickstart.html">Quickstart Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../overview.html">Overview</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../setup.html">Setup</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../operations.html">Operations</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../../../developers.html">Developers</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../../../contribute.html">We need your help</a></li>
<li class="toctree-l2"><a class="reference internal" href="../documentation.html">Contribute docs</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../developer.html">Contribute code and tests</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cyrusworks.html">Cyrus.Works</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="../../../developers.html#cyrus-internals">Cyrus Internals</a><ul class="current">
<li class="toctree-l3 current"><a class="reference internal" href="../API.html">Cyrus APIs</a><ul class="current">
<li class="toctree-l4"><a class="reference internal" href="cyrusdb.html">CyrusDB API</a></li>
<li class="toctree-l4"><a class="reference internal" href="cyrusdb2.html">cyrusdb API</a></li>
<li class="toctree-l4 current"><a class="current reference internal" href="#">Index API</a></li>
<li class="toctree-l4"><a class="reference internal" href="mailbox-api.html">Mailbox API</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../thoughts.html">Thoughts &amp; Notes</a></li>
<li class="toctree-l3"><a class="reference internal" href="../guidance.html">Guidance for Developers</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../../../developers.html#unit-tests">Unit Tests</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../../support.html">Support/Community</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Cyrus SASL</span></p>
<ul>
<li class="toctree-l1"><a class="reference external" href="http://www.cyrusimap.org/sasl">Cyrus SASL</a></li>
</ul>

        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../../../index.html">Cyrus IMAP</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="../../../index.html" class="icon icon-home" aria-label="Home"></a></li>
          <li class="breadcrumb-item"><a href="../../../developers.html">Developers</a></li>
          <li class="breadcrumb-item"><a href="../API.html">Developer APIs</a></li>
      <li class="breadcrumb-item active">Index API</li>
      <li class="wy-breadcrumbs-aside">
              <a href="https://github.com/cyrusimap/cyrus-imapd/blob/master/docsrc/imap/developer/API/index-api.rst" class="fa fa-github"> Edit on GitHub</a>
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <span class="target" id="imap-developer-api-index"></span><section id="index-api">
<h1>Index API<a class="headerlink" href="#index-api" title="Permalink to this heading"></a></h1>
<section id="intro">
<h2>Intro<a class="headerlink" href="#intro" title="Permalink to this heading"></a></h2>
<p>The Index API is implemented in <code class="docutils literal notranslate"><span class="pre">imap/index.h</span></code> and <code class="docutils literal notranslate"><span class="pre">imap/index.c</span></code>.
It provides a snapshot view into the underlying mailbox (see <cite>the
Mailbox API documentation &lt;mailbox-api.html&gt;</cite>) which obeys IMAP
semantics, as well as all the searching and sorting logic.</p>
</section>
<section id="opening-and-closing">
<h2>Opening and closing<a class="headerlink" href="#opening-and-closing" title="Permalink to this heading"></a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">index_state</span> <span class="o">*</span><span class="n">state</span> <span class="o">=</span> <span class="n">NULL</span><span class="p">;</span>
<span class="n">struct</span> <span class="n">index_init</span> <span class="n">init</span><span class="p">;</span>
<span class="nb">int</span> <span class="n">r</span><span class="p">;</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">mboxname</span> <span class="o">=</span> <span class="s2">&quot;user.brong&quot;</span><span class="p">;</span>

<span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">init</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">struct</span> <span class="n">index_init</span><span class="p">));</span>
<span class="n">init</span><span class="o">.</span><span class="n">userid</span> <span class="o">=</span> <span class="n">imapd_userid</span><span class="p">;</span>
<span class="n">init</span><span class="o">.</span><span class="n">authstate</span> <span class="o">=</span> <span class="n">imapd_authstate</span><span class="p">;</span>
<span class="n">init</span><span class="o">.</span><span class="n">out</span> <span class="o">=</span> <span class="n">imapd_out</span><span class="p">;</span>

<span class="n">r</span> <span class="o">=</span> <span class="n">index_open</span><span class="p">(</span><span class="n">mboxname</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">init</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">state</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">r</span><span class="p">)</span> <span class="k">return</span> <span class="n">r</span><span class="p">;</span>

<span class="n">do_stuff</span><span class="p">(</span><span class="n">state</span><span class="p">);</span>

<span class="n">index_close</span><span class="p">(</span><span class="o">&amp;</span><span class="n">state</span><span class="p">);</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">index_init</span></code> interface sucks. So does passing lots of parameters.
For now, this will do! Just pass NULL if you're only reading, or use the
code already in imapd and you'll be fine.</p>
</section>
<section id="the-index-model">
<h2>The Index Model<a class="headerlink" href="#the-index-model" title="Permalink to this heading"></a></h2>
<p>Ok - I think a few words about the index model and how it differs from
direct mailbox access are needed! In the past, index.c used pointers
directly into the mmaped <code class="docutils literal notranslate"><span class="pre">cyrus.index</span></code> file and maintained the old
mmaped copy if an expunge took place. Under the namelock regime, this is
no longer required because namelocks will avoid the file being
re-written.</p>
<p>Also, memory is now cheap. Rather than using locks to ensure
consistency, we just keep a copy of the <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">index_record</span></code> for even
message in the index, stored in memory. Since these are about 100 bytes
each, a 1 million email mailbox will take rougly 100Mb of memory. That's
not too bad on a modern server, and that's a <strong>huge</strong> mailbox.</p>
<p>So - the model works like this:</p>
<ul>
<li><p>Create the index state or re-lock (<code class="docutils literal notranslate"><span class="pre">index_lock</span></code>) the mailbox on an
existing index.</p></li>
<li><p>call <code class="docutils literal notranslate"><span class="pre">index_refresh</span></code></p></li>
<li><p>if any changes are to be made (i.e. flag updates for a store,
non-peek body fetch, expunge) then cycle through the refreshed state
map and update the records which are affected.</p></li>
<li><p>call <code class="docutils literal notranslate"><span class="pre">index_unlock</span></code> (unlock the underlying mailbox and commit the
statuscache changes)</p>
<p>At this point the index lock is <strong>released</strong> and we have not yet
generated any network traffic. Now start generating the response.</p>
</li>
<li><p>if expunges are allowed, call <code class="docutils literal notranslate"><span class="pre">index_tellexpunge</span></code></p></li>
<li><p>call <code class="docutils literal notranslate"><span class="pre">index_tellchanges</span></code> to tell about all other changes</p></li>
<li><p>return any response that the command itself required</p></li>
</ul>
</section>
</section>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="cyrusdb2.html" class="btn btn-neutral float-left" title="cyrusdb API" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
        <a href="mailbox-api.html" class="btn btn-neutral float-right" title="Mailbox API" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 1993–2025, The Cyrus Team.</p>
  </div>

  Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
    provided by <a href="https://readthedocs.org">Read the Docs</a>.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>
 



</body>
</html>