AIODiskIOStrategy.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /*
10  * Author: Adrian Chadd <adrian@squid-cache.org>
11  *
12  * These routines are simple plugin replacements for the file_* routines
13  * in disk.c . They back-end into the POSIX AIO routines to provide
14  * a nice and simple async IO framework for COSS.
15  *
16  * AIO is suitable for COSS - the only sync operations that the standard
17  * supports are read/write, and since COSS works on a single file
18  * per storedir it should work just fine.
19  */
20 
21 #include "squid.h"
22 #include "DiskIO/AIO/AIODiskFile.h"
24 #include "DiskIO/IORequestor.h"
25 #include "DiskIO/ReadRequest.h"
26 #include "DiskIO/WriteRequest.h"
27 
28 AIODiskIOStrategy::AIODiskIOStrategy() :
29  fd(-1)
30 {
31  aq.aq_state = AQ_STATE_NONE;
32  aq.aq_numpending = 0;
33  memset(&aq.aq_queue, 0, sizeof(aq.aq_queue));
34 }
35 
36 AIODiskIOStrategy::~AIODiskIOStrategy()
37 {
38  assert(aq.aq_state == AQ_STATE_SETUP ||
39  aq.aq_numpending == 0);
40 
41  sync();
42  aq.aq_state = AQ_STATE_NONE;
43 }
44 
45 bool
46 AIODiskIOStrategy::shedLoad()
47 {
48  return false;
49 }
50 
51 int
52 AIODiskIOStrategy::load()
53 {
54  return aq.aq_numpending * 1000 / MAX_ASYNCOP;
55 }
56 
58 AIODiskIOStrategy::newFile (char const *path)
59 {
60  if (shedLoad()) {
61  return nullptr;
62  }
63 
64  return new AIODiskFile (path, this);
65 }
66 
67 void
68 AIODiskIOStrategy::sync()
69 {
70  assert(aq.aq_state == AQ_STATE_SETUP);
71 
72  /*
73  * Keep calling callback to complete ops until the queue is empty
74  * We can't quit when callback returns 0 - some calls may not
75  * return any completed pending events, but they're still pending!
76  */
77 
78  while (aq.aq_numpending)
79  callback();
80 }
81 
82 bool
83 AIODiskIOStrategy::unlinkdUseful() const
84 {
85  return false;
86 }
87 
88 void
89 AIODiskIOStrategy::unlinkFile (char const *)
90 {}
91 
92 /*
93  * Note: we grab the state and free the state before calling the callback
94  * because this allows us to cut down the amount of time it'll take
95  * to find a free slot (since if we call the callback first, we're going
96  * to probably be allocated the slot _after_ this one..)
97  *
98  * I'll make it much more optimal later.
99  */
100 int
101 AIODiskIOStrategy::callback()
102 {
103  return 0;
104 #if 0
105  int i;
106  int retval, reterr;
107  FREE *freefunc;
108  void *cbdata;
109  int callback_valid;
110  void *buf;
111  async_queue_entry_t *aqe;
112  async_queue_entry_type_t type;
113 
114  assert(aq.aq_state == AQ_STATE_SETUP);
115 
116  /* Loop through all slots */
117 
118  for (i = 0; i < MAX_ASYNCOP; ++i) {
119  if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_USED) {
120  aqe = &aq.aq_queue[i];
121  /* Active, get status */
122  reterr = aio_error(&aqe->aq_e_aiocb);
123 
124  if (reterr < 0) {
125  fatal("aio_error returned an error!\n");
126  }
127 
128  if (reterr != EINPROGRESS) {
129  /* Get the return code */
130  retval = aio_return(&aqe->aq_e_aiocb);
131 
132  /* Get the callback parameters */
133  freefunc = aqe->aq_e_free;
134  buf = aqe->aq_e_buf;
135  type = aqe->aq_e_type;
136  callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata);
137  AIODiskFile * theFile = nullptr;
138  void *theFileVoid = nullptr;
139  void *theTmpFile = aqe->theFile;
140  bool fileOk = cbdataReferenceValidDone(theTmpFile, &theFileVoid);
141 
142  if (fileOk) {
143  theFile = static_cast<AIODiskFile *>(theFileVoid);
144  }
145 
146  /* Free slot */
147  memset(aqe, 0, sizeof(async_queue_entry_t));
148 
149  aqe->aq_e_state = AQ_ENTRY_FREE;
150 
151  --aq.aq_numpending;
152 
153  /* Callback */
154 
155  if (callback_valid) {
156  assert (fileOk);
157 
158  if (type == AQ_ENTRY_READ)
159  theFile->ioRequestor->readCompleted((const char *)buf, retval, reterr, static_cast<ReadRequest *>(cbdata));
160 
161  if (type == AQ_ENTRY_WRITE)
162  theFile->ioRequestor->writeCompleted(reterr,retval, static_cast<WriteRequest *>(cbdata));
163  }
164 
165  if (type == AQ_ENTRY_WRITE && freefunc)
166  freefunc(buf);
167  }
168  }
169  }
170 
171  return 0;
172 #endif
173 }
174 
175 void
176 AIODiskIOStrategy::init()
177 {
178  /* Make sure the queue isn't setup */
179  assert(aq.aq_state == AQ_STATE_NONE);
180 
181  /* Loop through, blanking the queue entries */
182 
183  /* Done */
184  aq.aq_state = AQ_STATE_SETUP;
185 }
186 
187 void
188 AIODiskIOStrategy::statfs(StoreEntry &) const
189 {}
190 
191 ConfigOption *
192 AIODiskIOStrategy::getOptionTree() const
193 {
194  return nullptr;
195 }
196 
197 /*
198  * find a free aio slot.
199  * Return the index, or -1 if we can't find one.
200  */
201 int
202 AIODiskIOStrategy::findSlot()
203 {
204  /* Later we should use something a little more .. efficient :) */
205 
206  for (int i = 0; i < MAX_ASYNCOP; ++i) {
207  if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE)
208  /* Found! */
209  return i;
210  }
211 
212  /* found nothing */
213  return -1;
214 }
215 
void fatal(const char *message)
Definition: fatal.cc:28
#define cbdataReferenceValidDone(var, ptr)
Definition: cbdata.h:239
void FREE(void *)
Definition: forward.h:37
Definition: cbdata.cc:37
#define assert(EX)
Definition: assert.h:17

 

Introduction

Documentation

Support

Miscellaneous