VirtualBox

source: vbox/trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h@ 22349

Last change on this file since 22349 was 22309, checked in by vboxsync, 15 years ago

PDMAsyncCompletion: Add first part of the cache for file I/O

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.9 KB
Line 
1/* $Id: PDMAsyncCompletionFileInternal.h 22309 2009-08-17 20:59:28Z vboxsync $ */
2/** @file
3 * PDM Async I/O - Transport data asynchronous in R3 using EMT.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef ___PDMAsyncCompletionFileInternal_h
23#define ___PDMAsyncCompletionFileInternal_h
24
25#include <VBox/cfgm.h>
26#include <VBox/stam.h>
27#include <iprt/types.h>
28#include <iprt/file.h>
29#include <iprt/thread.h>
30#include <iprt/semaphore.h>
31#include <iprt/critsect.h>
32#include <iprt/avl.h>
33
34#include "PDMAsyncCompletionInternal.h"
35
36/** @todo: Revise the caching of tasks. We have currently four caches:
37 * Per endpoint task cache
38 * Per class cache
39 * Per endpoint task segment cache
40 * Per class task segment cache
41 *
42 * We could use the RT heap for this probably or extend MMR3Heap (uses RTMemAlloc
43 * instead of managing larger blocks) to have this global for the whole VM.
44 */
45
46RT_C_DECLS_BEGIN
47
48/**
49 * A few forward declerations.
50 */
51typedef struct PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
52/** Pointer to a request segment. */
53typedef struct PDMACTASKFILE *PPDMACTASKFILE;
54/** Pointer to the endpoint class data. */
55typedef struct PDMASYNCCOMPLETIONTASKFILE *PPDMASYNCCOMPLETIONTASKFILE;
56/** Pointer to a cache LRU list. */
57typedef struct PDMACFILELRULIST *PPDMACFILELRULIST;
58/** Pointer to the global cache structure. */
59typedef struct PDMACFILECACHEGLOBAL *PPDMACFILECACHEGLOBAL;
60
61/**
62 * Blocking event types.
63 */
64typedef enum PDMACEPFILEAIOMGRBLOCKINGEVENT
65{
66 /** Invalid tye */
67 PDMACEPFILEAIOMGRBLOCKINGEVENT_INVALID = 0,
68 /** An endpoint is added to the manager. */
69 PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT,
70 /** An endpoint is removed from the manager. */
71 PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT,
72 /** An endpoint is about to be closed. */
73 PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT,
74 /** The manager is requested to terminate */
75 PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN,
76 /** The manager is requested to suspend */
77 PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND,
78 /** The manager is requested to resume */
79 PDMACEPFILEAIOMGRBLOCKINGEVENT_RESUME,
80 /** 32bit hack */
81 PDMACEPFILEAIOMGRBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
82} PDMACEPFILEAIOMGRBLOCKINGEVENT;
83
84/**
85 * States of the I/O manager.
86 */
87typedef enum PDMACEPFILEMGRSTATE
88{
89 /** Invalid state. */
90 PDMACEPFILEMGRSTATE_INVALID = 0,
91 /** Normal running state accepting new requests
92 * and processing them.
93 */
94 PDMACEPFILEMGRSTATE_RUNNING,
95 /** Fault state - not accepting new tasks for endpoints but waiting for
96 * remaining ones to finish.
97 */
98 PDMACEPFILEMGRSTATE_FAULT,
99 /** Suspending state - not accepting new tasks for endpoints but waiting
100 * for remaining ones to finish.
101 */
102 PDMACEPFILEMGRSTATE_SUSPENDING,
103 /** Shutdown state - not accepting new tasks for endpoints but waiting
104 * for remaining ones to finish.
105 */
106 PDMACEPFILEMGRSTATE_SHUTDOWN,
107 /** 32bit hack */
108 PDMACEPFILEMGRSTATE_32BIT_HACK = 0x7fffffff
109} PDMACEPFILEMGRSTATE;
110
111/**
112 * State of a async I/O manager.
113 */
114typedef struct PDMACEPFILEMGR
115{
116 /** Next Aio manager in the list. */
117 R3PTRTYPE(struct PDMACEPFILEMGR *) pNext;
118 /** Previous Aio manager in the list. */
119 R3PTRTYPE(struct PDMACEPFILEMGR *) pPrev;
120 /** Current state of the manager. */
121 PDMACEPFILEMGRSTATE enmState;
122 /** Event semaphore the manager sleeps on when waiting for new requests. */
123 RTSEMEVENT EventSem;
124 /** Flag whether the thread waits in the event semaphore. */
125 volatile bool fWaitingEventSem;
126 /** Flag whether this manager uses the failsafe method. */
127 bool fFailsafe;
128 /** Thread data */
129 RTTHREAD Thread;
130 /** The async I/O context for this manager. */
131 RTFILEAIOCTX hAioCtx;
132 /** Flag whether the I/O manager was woken up. */
133 volatile bool fWokenUp;
134 /** List of endpoints assigned to this manager. */
135 R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointsHead;
136 /** Number of requests active currently. */
137 unsigned cRequestsActive;
138 /** Pointer to an array of free async I/O request handles. */
139 RTFILEAIOREQ *pahReqsFree;
140 /** Next free position for a free request handle. */
141 unsigned iFreeEntryNext;
142 /** Position of the next free task handle */
143 unsigned iFreeReqNext;
144 /** Size of the array. */
145 unsigned cReqEntries;
146 /** Critical section protecting the blocking event handling. */
147 RTCRITSECT CritSectBlockingEvent;
148 /** Event sempahore for blocking external events.
149 * The caller waits on it until the async I/O manager
150 * finished processing the event. */
151 RTSEMEVENT EventSemBlock;
152 /** Flag whether a blocking event is pending and needs
153 * processing by the I/O manager. */
154 volatile bool fBlockingEventPending;
155 /** Blocking event type */
156 volatile PDMACEPFILEAIOMGRBLOCKINGEVENT enmBlockingEvent;
157 /** Event type data */
158 union
159 {
160 /** Add endpoint event. */
161 struct
162 {
163 /** The endpoint to be added */
164 volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
165 } AddEndpoint;
166 /** Remove endpoint event. */
167 struct
168 {
169 /** The endpoint to be removed */
170 volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
171 } RemoveEndpoint;
172 /** Close endpoint event. */
173 struct
174 {
175 /** The endpoint to be closed */
176 volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
177 } CloseEndpoint;
178 } BlockingEventData;
179} PDMACEPFILEMGR;
180/** Pointer to a async I/O manager state. */
181typedef PDMACEPFILEMGR *PPDMACEPFILEMGR;
182/** Pointer to a async I/O manager state pointer. */
183typedef PPDMACEPFILEMGR *PPPDMACEPFILEMGR;
184
185/**
186 * Data for one request segment waiting for cache entry.
187 */
188typedef struct PDMACFILETASKSEG
189{
190 /** Next task segment in the list. */
191 struct PDMACFILETASKSEG *pNext;
192 /** Task this segment is for. */
193 PPDMASYNCCOMPLETIONTASKFILE pTask;
194 /** Offset into the cache entry buffer to start reading from. */
195 uint32_t uBufOffset;
196 /** Number of bytes to transfer. */
197 size_t cbTransfer;
198 /** Pointer to the buffer. */
199 void *pvBuf;
200 /** Flag whether this entry writes data to the cache. */
201 bool fWrite;
202} PDMACFILETASKSEG, *PPDMACFILETASKSEG;
203
204/**
205 * A cache entry
206 */
207typedef struct PDMACFILECACHEENTRY
208{
209 /** The AVL entry data. */
210 AVLRFOFFNODECORE Core;
211 /** Pointer to the previous element. Used in one of the LRU lists.*/
212 struct PDMACFILECACHEENTRY *pPrev;
213 /** Pointer to the next element. Used in one of the LRU lists.*/
214 struct PDMACFILECACHEENTRY *pNext;
215 /** Pointer to the list the entry is in. */
216 PPDMACFILELRULIST pList;
217 /** Pointer to the global cache structure. */
218 PPDMACFILECACHEGLOBAL pCache;
219 /** Endpoint the entry belongs to. */
220 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
221 /** Flags for this entry. Combinations of PDMACFILECACHE_* #defines */
222 uint32_t fFlags;
223 /** Size of the entry. */
224 size_t cbData;
225 /** Pointer to the memory containing the data. */
226 uint8_t *pbData;
227 /** List of tasks waiting for this one to finish. */
228 PPDMACFILETASKSEG pHead;
229} PDMACFILECACHEENTRY, *PPDMACFILECACHEENTRY;
230/** I/O is still in progress for this entry. This entry is not evictable. */
231#define PDMACFILECACHE_ENTRY_IO_IN_PROGRESS RT_BIT(0)
232/** Entry is locked and thus not evictable. */
233#define PDMACFILECACHE_ENTRY_LOCKED RT_BIT(1)
234/** Entry is dirty */
235#define PDMACFILECACHE_ENTRY_IS_DIRTY RT_BIT(2)
236/** Entry is not evictable. */
237#define PDMACFILECACHE_NOT_EVICTABLE (PDMACFILECACHE_ENTRY_LOCKED | PDMACFILECACHE_IO_IN_PROGRESS)
238
239/**
240 * LRU list data
241 */
242typedef struct PDMACFILELRULIST
243{
244 /** Head of the list. */
245 PPDMACFILECACHEENTRY pHead;
246 /** Tail of the list. */
247 PPDMACFILECACHEENTRY pTail;
248 /** Number of bytes cached in the list. */
249 uint32_t cbCached;
250} PDMACFILELRULIST;
251
252/**
253 * Global cache data.
254 */
255typedef struct PDMACFILECACHEGLOBAL
256{
257 /** Maximum size of the cache in bytes. */
258 uint32_t cbMax;
259 /** Current size of the cache in bytes. */
260 uint32_t cbCached;
261 /** Critical section protecting the cache. */
262 RTCRITSECT CritSect;
263 /** Adaption parameter (p) */
264 uint32_t uAdaptVal;
265 /** LRU list for recently used entries (T1) */
266 PDMACFILELRULIST LruRecentlyUsed;
267 /** LRU list for frequently used entries (T2) */
268 PDMACFILELRULIST LruFrequentlyUsed;
269 /** LRU list for recently evicted entries (B1) */
270 PDMACFILELRULIST LruRecentlyGhost;
271 /** LRU list for evicted entries from T2 (B2) */
272 PDMACFILELRULIST LruFrequentlyGhost;
273#ifdef VBOX_WITH_STATISTICS
274 /** Hit counter. */
275 STAMCOUNTER cHits;
276 /** Partial hit counter. */
277 STAMCOUNTER cPartialHits;
278 /** Miss counter. */
279 STAMCOUNTER cMisses;
280 /** Bytes read from cache. */
281 STAMCOUNTER StatRead;
282 /** Bytes written to the cache. */
283 STAMCOUNTER StatWritten;
284 /** Time spend to get an entry in the AVL tree. */
285 STAMPROFILEADV StatTreeGet;
286 /** Time spend to insert an entry in the AVL tree. */
287 STAMPROFILEADV StatTreeInsert;
288 /** Time spend to remove an entry in the AVL tree. */
289 STAMPROFILEADV StatTreeRemove;
290#endif
291} PDMACFILECACHEGLOBAL;
292
293/**
294 * Per endpoint cache data.
295 */
296typedef struct PDMACFILEENDPOINTCACHE
297{
298 /** AVL tree managing cache entries. */
299 PAVLRFOFFTREE pTree;
300 /** Critical section protecting the tree. */
301 RTCRITSECT CritSect;
302 /** Pointer to the gobal cache data */
303 PPDMACFILECACHEGLOBAL pCache;
304} PDMACFILEENDPOINTCACHE, *PPDMACFILEENDPOINTCACHE;
305
306/**
307 * Global data for the file endpoint class.
308 */
309typedef struct PDMASYNCCOMPLETIONEPCLASSFILE
310{
311 /** Common data. */
312 PDMASYNCCOMPLETIONEPCLASS Core;
313 /** Flag whether we use the failsafe method. */
314 bool fFailsafe;
315 /** Critical section protecting the list of async I/O managers. */
316 RTCRITSECT CritSect;
317 /** Pointer to the head of the async I/O managers. */
318 R3PTRTYPE(PPDMACEPFILEMGR) pAioMgrHead;
319 /** Number of async I/O managers currently running. */
320 unsigned cAioMgrs;
321 /** Maximum number of segments to cache per endpoint */
322 unsigned cTasksCacheMax;
323 /** Maximum number of simultaneous outstandingrequests. */
324 uint32_t cReqsOutstandingMax;
325 /** Bitmask for checking the alignment of a buffer. */
326 RTR3UINTPTR uBitmaskAlignment;
327 /** Global cache data. */
328 PDMACFILECACHEGLOBAL Cache;
329} PDMASYNCCOMPLETIONEPCLASSFILE;
330/** Pointer to the endpoint class data. */
331typedef PDMASYNCCOMPLETIONEPCLASSFILE *PPDMASYNCCOMPLETIONEPCLASSFILE;
332
333typedef enum PDMACEPFILEBLOCKINGEVENT
334{
335 /** The invalid event type */
336 PDMACEPFILEBLOCKINGEVENT_INVALID = 0,
337 /** A task is about to be canceled */
338 PDMACEPFILEBLOCKINGEVENT_CANCEL,
339 /** Usual 32bit hack */
340 PDMACEPFILEBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
341} PDMACEPFILEBLOCKINGEVENT;
342
343/**
344 * States of the endpoint.
345 */
346typedef enum PDMASYNCCOMPLETIONENDPOINTFILESTATE
347{
348 /** Invalid state. */
349 PDMASYNCCOMPLETIONENDPOINTFILESTATE_INVALID = 0,
350 /** Normal running state accepting new requests
351 * and processing them.
352 */
353 PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE,
354 /** The endpoint is about to be closed - not accepting new tasks for endpoints but waiting for
355 * remaining ones to finish.
356 */
357 PDMASYNCCOMPLETIONENDPOINTFILESTATE_CLOSING,
358 /** Removing from current I/O manager state - not processing new tasks for endpoints but waiting
359 * for remaining ones to finish.
360 */
361 PDMASYNCCOMPLETIONENDPOINTFILESTATE_REMOVING,
362 /** The current endpoint will be migrated to another I/O manager. */
363 PDMASYNCCOMPLETIONENDPOINTFILESTATE_MIGRATING,
364 /** 32bit hack */
365 PDMASYNCCOMPLETIONENDPOINTFILESTATE_32BIT_HACK = 0x7fffffff
366} PDMASYNCCOMPLETIONENDPOINTFILESTATE;
367
368/**
369 * Data for the file endpoint.
370 */
371typedef struct PDMASYNCCOMPLETIONENDPOINTFILE
372{
373 /** Common data. */
374 PDMASYNCCOMPLETIONENDPOINT Core;
375 /** Current state of the endpoint. */
376 PDMASYNCCOMPLETIONENDPOINTFILESTATE enmState;
377 /** async I/O manager this endpoint is assigned to. */
378 R3PTRTYPE(volatile PPDMACEPFILEMGR) pAioMgr;
379 /** Flags for opening the file. */
380 unsigned fFlags;
381 /** File handle. */
382 RTFILE File;
383 /** Size of the underlying file.
384 * Updated while data is appended. */
385 uint64_t cbFile;
386 /** Flag whether caching is enabled for this file. */
387 bool fCaching;
388 /** Flag whether the file was opened readonly. */
389 bool fReadonly;
390 /** List of new tasks. */
391 R3PTRTYPE(volatile PPDMACTASKFILE) pTasksNewHead;
392
393 /** Head of the small cache for allocated task segments for exclusive
394 * use by this endpoint. */
395 R3PTRTYPE(volatile PPDMACTASKFILE) pTasksFreeHead;
396 /** Tail of the small cache for allocated task segments for exclusive
397 * use by this endpoint. */
398 R3PTRTYPE(volatile PPDMACTASKFILE) pTasksFreeTail;
399 /** Number of elements in the cache. */
400 volatile uint32_t cTasksCached;
401
402 /** Cache of endpoint data. */
403 PDMACFILEENDPOINTCACHE DataCache;
404
405 /** Flag whether a flush request is currently active */
406 PPDMACTASKFILE pFlushReq;
407
408 /** Event sempahore for blocking external events.
409 * The caller waits on it until the async I/O manager
410 * finished processing the event. */
411 RTSEMEVENT EventSemBlock;
412 /** Flag whether a blocking event is pending and needs
413 * processing by the I/O manager. */
414 bool fBlockingEventPending;
415 /** Blocking event type */
416 PDMACEPFILEBLOCKINGEVENT enmBlockingEvent;
417 /** Additional data needed for the event types. */
418 union
419 {
420 /** Cancelation event. */
421 struct
422 {
423 /** The task to cancel. */
424 PPDMACTASKFILE pTask;
425 } Cancel;
426 } BlockingEventData;
427 /** Data for exclusive use by the assigned async I/O manager. */
428 struct
429 {
430 /** Pointer to the next endpoint assigned to the manager. */
431 R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointNext;
432 /** Pointer to the previous endpoint assigned to the manager. */
433 R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointPrev;
434 /** List of pending requests (not submitted due to usage restrictions
435 * or a pending flush request) */
436 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingHead;
437 /** Tail of pending requests. */
438 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingTail;
439 /** Number of requests currently being processed for this endpoint
440 * (excluded flush requests). */
441 unsigned cRequestsActive;
442 /** Number of requests processed during the last second. */
443 unsigned cReqsPerSec;
444 /** Current number of processed requests for the current update period. */
445 unsigned cReqsProcessed;
446 } AioMgr;
447} PDMASYNCCOMPLETIONENDPOINTFILE;
448/** Pointer to the endpoint class data. */
449typedef PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
450
451/** Request completion function */
452typedef DECLCALLBACK(void) FNPDMACTASKCOMPLETED(PPDMACTASKFILE pTask, void *pvUser);
453/** Pointer to a request completion function. */
454typedef FNPDMACTASKCOMPLETED *PFNPDMACTASKCOMPLETED;
455
456/**
457 * Transfer type.
458 */
459typedef enum PDMACTASKFILETRANSFER
460{
461 /** Invalid. */
462 PDMACTASKFILETRANSFER_INVALID = 0,
463 /** Read transfer. */
464 PDMACTASKFILETRANSFER_READ,
465 /** Write transfer. */
466 PDMACTASKFILETRANSFER_WRITE,
467 /** Flush transfer. */
468 PDMACTASKFILETRANSFER_FLUSH
469} PDMACTASKFILETRANSFER;
470
471/**
472 * Data of a request.
473 */
474typedef struct PDMACTASKFILE
475{
476 /** next task in the list. */
477 struct PDMACTASKFILE *pNext;
478 /** Endpoint */
479 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
480 /** Transfer type. */
481 PDMACTASKFILETRANSFER enmTransferType;
482 /** Start offset */
483 RTFOFF Off;
484 /** Data segment. */
485 PDMDATASEG DataSeg;
486 /** Flag whether this segment uses a bounce buffer
487 * because the provided buffer doesn't meet host requirements. */
488 bool fBounceBuffer;
489 /** Pointer to the used bounce buffer if any. */
490 void *pvBounceBuffer;
491 /** Completion function to call on completion. */
492 PFNPDMACTASKCOMPLETED pfnCompleted;
493 /** User data */
494 void *pvUser;
495} PDMACTASKFILE;
496
497/**
498 * Per task data.
499 */
500typedef struct PDMASYNCCOMPLETIONTASKFILE
501{
502 /** Common data. */
503 PDMASYNCCOMPLETIONTASK Core;
504 /** Number of bytes to transfer until this task completes. */
505 volatile int32_t cbTransferLeft;
506 /** Flag whether the task completed. */
507 volatile bool fCompleted;
508} PDMASYNCCOMPLETIONTASKFILE;
509
510int pdmacFileAioMgrFailsafe(RTTHREAD ThreadSelf, void *pvUser);
511int pdmacFileAioMgrNormal(RTTHREAD ThreadSelf, void *pvUser);
512
513int pdmacFileAioMgrNormalInit(PPDMACEPFILEMGR pAioMgr);
514void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr);
515
516PPDMACTASKFILE pdmacFileEpGetNewTasks(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
517PPDMACTASKFILE pdmacFileTaskAlloc(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
518void pdmacFileTaskFree(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
519 PPDMACTASKFILE pTask);
520
521int pdmacFileEpAddTask(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTask);
522
523void pdmacFileEpTaskCompleted(PPDMACTASKFILE pTask, void *pvUser);
524
525int pdmacFileCacheInit(PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile, PCFGMNODE pCfgNode);
526void pdmacFileCacheDestroy(PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
527int pdmacFileEpCacheInit(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
528void pdmacFileEpCacheDestroy(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
529
530int pdmacFileEpCacheRead(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
531 RTFOFF off, PCPDMDATASEG paSegments, size_t cSegments,
532 size_t cbRead);
533int pdmacFileEpCacheWrite(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
534 RTFOFF off, PCPDMDATASEG paSegments, size_t cSegments,
535 size_t cbWrite);
536
537RT_C_DECLS_END
538
539#endif
540
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette