Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3667 lines
152 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. frsalloc.h
  5. Abstract:
  6. Function and struct defs for FrsAlloc() and FrsFree().
  7. Author:
  8. David Orbits (davidor) - 3-Mar-1997
  9. Revision History:
  10. --*/
  11. #ifndef _FRSALLOC_
  12. #define _FRSALLOC_
  13. #include <genhash.h>
  14. #include <frserror.h>
  15. #define FrsAllocType(_Type_) FrsAllocTypeSize(_Type_, 0)
  16. #define ZERO_FID ((ULONGLONG)0)
  17. typedef struct _REPLICA_SERVICE_STATE_ {
  18. PFRS_QUEUE ServiceList;
  19. PCHAR Name;
  20. } REPLICA_SERVICE_STATE, *PREPLICA_SERVICE_STATE;
  21. extern REPLICA_SERVICE_STATE ReplicaServiceState[];
  22. //
  23. // Every struct allocated by FrsAllocate() starts with an FRS_NODE_HEADER.
  24. //
  25. typedef struct _FRS_NODE_HEADER {
  26. USHORT Type;
  27. USHORT Size;
  28. } FRS_NODE_HEADER, *PFRS_NODE_HEADER;
  29. //
  30. // Each different type of node allocated has a node type entry defined here.
  31. // Note - Any change here should be reflected in NodeTypeNames in frsalloc.c.
  32. //
  33. typedef enum _NODE_TYPE {
  34. THREAD_CONTEXT_TYPE = 16, // Per thread global context
  35. REPLICA_TYPE, // Per Replica Set Context
  36. REPLICA_THREAD_TYPE, // Context for a given replica set in the
  37. // environment of a given thread.
  38. CONFIG_NODE_TYPE, // node from the DS
  39. CXTION_TYPE, // a cxtion
  40. GHANDLE_TYPE, // a guid/rpc handle
  41. THREAD_TYPE, // generic thread context
  42. GEN_TABLE_TYPE, // generic table
  43. JBUFFER_TYPE, // NTFS Journal buffer
  44. VOLUME_MONITOR_ENTRY_TYPE, // NTFS Volume Journal state.
  45. COMMAND_PACKET_TYPE, // Subsystem command packet.
  46. GENERIC_HASH_TABLE_TYPE, // Generic hash table control struct.
  47. CHANGE_ORDER_ENTRY_TYPE, // ChangeOrder from journal.
  48. FILTER_TABLE_ENTRY_TYPE, // Journal Filter Entry.
  49. QHASH_TABLE_TYPE, // Parent File ID table base struct.
  50. OUT_LOG_PARTNER_TYPE, // Outbound log partner state.
  51. WILDCARD_FILTER_ENTRY_TYPE, // Wildcard filename filter entries.
  52. REPARSE_TAG_TABLE_ENTRY_TYPE, // ReparseTagTable entry.
  53. NODE_TYPE_MAX
  54. } NODE_TYPE;
  55. #define NODE_TYPE_MIN THREAD_CONTEXT_TYPE
  56. typedef struct _REPARSE_TAG_TABLE_ENTRY {
  57. FRS_NODE_HEADER Header;
  58. PWCHAR ReplicationType;
  59. } REPARSE_TAG_TABLE_ENTRY, *PREPARSE_TAG_TABLE_ENTRY;
  60. //
  61. // Some type defs missing from Jet.
  62. //
  63. typedef JET_INSTANCE *PJET_INSTANCE;
  64. typedef JET_TABLECREATE *PJET_TABLECREATE;
  65. typedef JET_SETCOLUMN *PJET_SETCOLUMN;
  66. typedef JET_RETRIEVECOLUMN *PJET_RETRIEVECOLUMN;
  67. typedef JET_SESID *PJET_SESID;
  68. typedef JET_DBID *PJET_DBID;
  69. typedef JET_TABLEID *PJET_TABLEID;
  70. typedef JET_INDEXCREATE *PJET_INDEXCREATE;
  71. typedef JET_COLUMNCREATE *PJET_COLUMNCREATE;
  72. /******************************************************************************
  73. *******************************************************************************
  74. ** **
  75. ** **
  76. ** S T A G E E N T R Y **
  77. ** **
  78. ** **
  79. *******************************************************************************
  80. ******************************************************************************/
  81. //
  82. // Access to the staging files is controlled by this data structure.
  83. // The structure is also used to manage the staging space.
  84. //
  85. // The change order guid is used as the key to the entry. The entries
  86. // are ordered in a gen table.
  87. //
  88. // The file size is used to reserve space. Granted the file's size is
  89. // only an approximation of the amount of disk space needed by the
  90. // staging file; but its all we have. It is better than nothing.
  91. //
  92. // Both the state of the staging file and its attributes are stored
  93. // in the Flags field.
  94. //
  95. // Attributes
  96. //
  97. #define STAGE_FLAG_RESERVE 0x00000001 // reserve staging space
  98. #define STAGE_FLAG_UNRESERVE 0x00000002 // release staging space
  99. #define STAGE_FLAG_FORCERESERVE 0x00000004 // force reserve
  100. #define STAGE_FLAG_EXCLUSIVE 0x00000008 // exclusive access
  101. #define STAGE_FLAG_RERESERVE 0x00000010 // rereserve staging space
  102. #define STAGE_FLAG_FILE_GUID 0x00000020 // entry is indexed by file guid
  103. #define STAGE_FLAG_STAGE_MANAGEMENT 0x00000040 // acquiring for data management
  104. #define STAGE_FLAG_ATTRIBUTE_MASK 0x0000FFFF
  105. //
  106. // States
  107. //
  108. #define STAGE_FLAG_CREATING 0x80000000 // staging file is being created
  109. #define STAGE_FLAG_DATA_PRESENT 0x40000000 // staging file awaiting final reaname.
  110. #define STAGE_FLAG_CREATED 0x20000000 // staging file has been created
  111. #define STAGE_FLAG_INSTALLING 0x10000000 // staging file is being installed
  112. #define STAGE_FLAG_INSTALLED 0x08000000 // staging file has been installed
  113. #define STAGE_FLAG_RECOVERING 0x04000000 // staging file is being recovered
  114. #define STAGE_FLAG_RECOVERED 0x02000000 // staging file has been recovered
  115. //
  116. // Flags needed for compression support.
  117. //
  118. #define STAGE_FLAG_COMPRESSED 0x01000000 // There is a compressed staging
  119. // staging file for this entry.
  120. #define STAGE_FLAG_DECOMPRESSED 0x00800000 // The staging file has been
  121. // decompressed once for a downlevel partner.
  122. #define STAGE_FLAG_COMPRESSION_FORMAT_KNOWN 0x00400000 // The CompressedGuid off the
  123. // STAGE_ENTRY structure is set.
  124. #define STAGE_FLAG_STATE_MASK 0xFFFF0000
  125. //
  126. // Stage entry
  127. //
  128. typedef struct _STAGE_ENTRY {
  129. // GUID CoGuid; // change order guid is the key
  130. GUID FileOrCoGuid; // index for the table. This is
  131. // the file guid if
  132. // STAGE_FLAG_FILE_GUID flag is set
  133. // else it is the change order guid.
  134. ULONG FileSizeInKb; // reserved space in kb
  135. ULONG CompressedFileSizeInKb; // Size of compressedfile if present.
  136. ULONG ReferenceCount; // for shared access during fetch
  137. ULONG Flags; // state and attributes
  138. GUID CompressionGuid; // Guid of the compression format that
  139. // was used to compress this staging file.
  140. DWORD StagingAreaIndex; // Index into the StagingAreaArray
  141. // for this replica set.
  142. DWORD FileVersionNumber; // Version number of the file.
  143. FILETIME LastAccessTime; // Last time this staging file was accessed
  144. DWORD ReplicaNumber; // Number of the replica set owning this stage
  145. // file.
  146. } STAGE_ENTRY, *PSTAGE_ENTRY;
  147. #define STAGE_FILE_TRACE(_sev, _guid, _fname, _size, _pflags, _text) \
  148. StageFileTrace(_sev, DEBSUB, __LINE__, _guid, _fname, &(_size), _pflags, _text)
  149. /******************************************************************************
  150. *******************************************************************************
  151. ** **
  152. ** **
  153. ** S T A G E _ A R E A _ E N T R Y **
  154. ** **
  155. ** **
  156. *******************************************************************************
  157. ******************************************************************************/
  158. //
  159. // The following structure defines each entry of the Staging area table. This is
  160. // a global table of all the staging areas available to FRS on this machine.
  161. // Each staging area is included once in the table even if it is shared by more
  162. // than one replica set. The ReferenceCount value of the entry specifies how many
  163. // replica sets are currently using this staging area.
  164. //
  165. //
  166. // The StagingAreaState variable of the STAGE_AREA_ENTRY structure can have one
  167. // of the following values.
  168. //
  169. #define STAGING_AREA_ELIGIBLE 0x1
  170. #define STAGING_AREA_DISABLED 0x2
  171. #define STAGING_AREA_DELETED 0x3
  172. #define STAGING_AREA_AT_QUOTA 0x4
  173. #define STAGING_AREA_DISK_FULL 0x5
  174. #define STAGING_AREA_ERROR 0x6
  175. typedef struct _STAGING_AREA_ENTRY {
  176. CRITICAL_SECTION StagingAreaCritSec; // Critical section to serialize
  177. // updates to items in this entry.
  178. PWCHAR StagingArea; // Absolute path to the staging directory.
  179. ULONG StagingAreaLimitInKB; // Staging area limit.
  180. ULONG StagingAreaSpaceInUse; // Current staging space in use under
  181. // this area.
  182. DWORD StagingAreaState; // State of this staging area.
  183. DWORD ReferenceCount; // Number of replica sets using
  184. // this staging area.
  185. }STAGING_AREA_ENTRY, *PSTAGING_AREA_ENTRY;
  186. /******************************************************************************
  187. *******************************************************************************
  188. ** **
  189. ** **
  190. ** T H R E A D _ C T X **
  191. ** **
  192. ** **
  193. *******************************************************************************
  194. ******************************************************************************/
  195. //
  196. // The following struct defines the per-thread global context. i.e. it is not
  197. // replica specific.
  198. //
  199. typedef struct _THREAD_CTX {
  200. FRS_NODE_HEADER Header;
  201. ULONG ThreadType; // Main thread, update thread, ...
  202. LIST_ENTRY ThreadListEntry; // List of all threads in the process.
  203. FRS_LIST ThreadCtxListHead; // Head of all open REPLICA_THREAD_CTX's for this thread.
  204. JET_INSTANCE JInstance; // Jet Instance
  205. JET_SESID JSesid; // Session ID for this thread
  206. JET_DBID JDbid; // Database ID for this thread
  207. } THREAD_CTX, *PTHREAD_CTX;
  208. /******************************************************************************
  209. *******************************************************************************
  210. ** **
  211. ** **
  212. ** T A B L E _ C T X **
  213. ** **
  214. ** **
  215. *******************************************************************************
  216. ******************************************************************************/
  217. struct _RECORD_FIELDS;
  218. //
  219. // The following struct defines the context for an instance of an open table.
  220. //
  221. typedef struct _TABLE_CTX {
  222. JET_TABLEID Tid; // Jet Table ID.
  223. ULONG ReplicaNumber; // Table belongs to this Replica Number
  224. ULONG TableType; // The type code of this table.
  225. ULONG PropertyFlags; // see schema.h
  226. JET_SESID Sesid; // The Jet session id when table opened.
  227. PJET_TABLECREATE pJetTableCreate; // Table create info
  228. struct _RECORD_FIELDS *pRecordFields; // Field descriptor for this record.
  229. PJET_SETCOLUMN pJetSetCol; // Struct to write Config
  230. PJET_RETRIEVECOLUMN pJetRetCol; // Struct to read Config
  231. PVOID pDataRecord; // Data record storage
  232. } TABLE_CTX, *PTABLE_CTX;
  233. /******************************************************************************
  234. *******************************************************************************
  235. ** **
  236. ** **
  237. ** R E P L I C A _ T H R E A D _ C T X **
  238. ** **
  239. ** **
  240. *******************************************************************************
  241. ******************************************************************************/
  242. //
  243. // The following struct defines the per-thread replica context. Each thread
  244. // needs its own set of table IDs for the replica, its own table records and
  245. // its own replica context when doing work on a given replica.
  246. //
  247. // ** NOTE ** The correct value for TABLE_TYPE_MAX comes from schema.h
  248. // any module that uses this struct must include schema.h first.
  249. // We undef this at the end to possibly generate a compile error.
  250. //
  251. typedef struct _REPLICA_THREAD_CTX {
  252. FRS_NODE_HEADER Header;
  253. //
  254. // The order of the table context structs MUST be in the same order as
  255. // the members of the TABLE_TYPE enum defined in schema.h so they
  256. // can be accessed as an array.
  257. //
  258. union {
  259. struct {
  260. TABLE_CTX INLOGTable;
  261. TABLE_CTX OUTLOGTable;
  262. TABLE_CTX IDTable;
  263. TABLE_CTX DIRTable;
  264. TABLE_CTX VVTable;
  265. TABLE_CTX CXTIONTable;
  266. };
  267. TABLE_CTX RtCtxTables[TABLE_TYPE_MAX];
  268. };
  269. // Tunnel Table
  270. JET_TABLEID JetSortTbl; // Temp table for sorting
  271. JET_COLUMNID SortColumns[2]; // ColumnIDs for the two columns in the
  272. // sort table.
  273. LIST_ENTRY ThreadCtxList; // Links all contexts assoc with this thread.
  274. LIST_ENTRY ReplicaCtxList; // Links all contexts assoc with this replica set.
  275. // ULONG OpenTransCount; // open transactions for this thread
  276. // LCID dwLcid; // Locale to use for Unicode compares. Null
  277. // means to use a default sort
  278. // Put all DBG components at end of structure so that dsexts routines
  279. // can easily ignore them (and get all other fields right) in both
  280. // debug and free builds.
  281. #if DBG
  282. // ULONG MemSize; // The running total of memory allocated
  283. // ULONG OrgSize; // The running total of memory allocated
  284. // LONG cJetSess; // jet session count for this thread
  285. #endif
  286. } REPLICA_THREAD_CTX, *PREPLICA_THREAD_CTX;
  287. //
  288. // Call FrsAllocTypeSize() with the following flag in the size parameter
  289. // to only allocate a RtCtx struct with minimal TableCtx init. No call
  290. // to DbsAllocTableCtx() is made on the individual replica tables.
  291. //
  292. #define FLAG_FRSALLOC_NO_ALLOC_TBL_CTX 0x1
  293. /******************************************************************************
  294. *******************************************************************************
  295. ** **
  296. ** **
  297. ** S T A G E H E A D E R **
  298. ** **
  299. ** **
  300. *******************************************************************************
  301. ******************************************************************************/
  302. //
  303. // Header at the beginning of every stage file.
  304. //
  305. typedef struct _STAGE_HEADER_ {
  306. ULONG Major; // MUST BE FIRST major version
  307. ULONG Minor; // MUST BE SECOND minor version
  308. ULONG DataHigh; // offset from beginning of file to data
  309. ULONG DataLow; // offset from beginning of file to data
  310. //
  311. // NTFRS_STAGE_MINOR_0
  312. //
  313. // compression mode of the original source file as stored in NTFS.
  314. USHORT Compression;
  315. FILE_NETWORK_OPEN_INFORMATION Attributes;
  316. CHANGE_ORDER_COMMAND ChangeOrderCommand;
  317. FILE_OBJECTID_BUFFER FileObjId;
  318. //
  319. // NTFRS_STAGE_MINOR_1 (must remain at the WIN2K size for interop compat.)
  320. //
  321. CO_RECORD_EXTENSION_WIN2K CocExt;
  322. //
  323. // NTFRS_STAGE_MINOR_2
  324. // The compression Guid identifies the compression algorithm used on
  325. // the stage file data.
  326. //
  327. GUID CompressionGuid;
  328. //
  329. // The Data offsets above allow us to find the beginning of the backup
  330. // restore data so the Stage Header is extensible.
  331. //
  332. // Only Add new data to this structure here and adjust the minor
  333. // version number so Up-Rev members can tell when an incoming stage file
  334. // was generated by another Up-Rev member. The layout of the data above
  335. // can never change or down-rev members will break when given an up-rev
  336. // stage file.
  337. //
  338. //
  339. // To support replication of encrypted data we need to store the offset and
  340. // size of the RawEncrypted data read using the RawFile APIs
  341. //
  342. ULONG EncryptedDataHigh; // offset from beginning of file to encrypted data
  343. ULONG EncryptedDataLow; // offset from beginning of file to encrypted data
  344. LARGE_INTEGER EncryptedDataSize; // size of encrypted data.
  345. //
  346. // NTFRS_STAGE_MINOR_3
  347. //
  348. BOOL ReparseDataPresent; // Is there reparse data in this file?
  349. ULONG ReparsePointDataHigh; // offset from beginning of file to reparse data
  350. ULONG ReparsePointDataLow; // offset from beginning of file to reparse data
  351. }STAGE_HEADER, *PSTAGE_HEADER;
  352. /******************************************************************************
  353. *******************************************************************************
  354. ** **
  355. ** **
  356. ** C O N F I G _ N O D E **
  357. ** **
  358. ** **
  359. *******************************************************************************
  360. ******************************************************************************/
  361. //
  362. // We build an incore copy of the DS hierarchy sites\settings\servers\cxtions.
  363. // Hence the interrelated structs for site, settings, server, and cxtion.
  364. //
  365. // The node struct is a generic node created with info from the DS tree.
  366. //
  367. // XXX The uSNCreated is being used as a GUID!
  368. //
  369. //
  370. // The state of nodes as they migrate to/from the DB
  371. //
  372. //
  373. // The generic table routines can't handle dups or multithreading. So
  374. // we provide wrapper routines that add duplicate key proccessing and
  375. // multithreading.
  376. //
  377. typedef struct _GEN_ENTRY GEN_ENTRY, *PGEN_ENTRY;
  378. struct _GEN_ENTRY {
  379. PVOID Data; // The real entry in the table
  380. GUID *Key1; // For compares
  381. PWCHAR Key2; // For compares (may be NULL)
  382. PGEN_ENTRY Dups; // remember dups
  383. };
  384. //
  385. // A generic table with a lock and duplicate processing
  386. //
  387. typedef struct _GEN_TABLE {
  388. FRS_NODE_HEADER Header; // Memory management
  389. CRITICAL_SECTION Critical; // critical section
  390. RTL_GENERIC_TABLE Table; // RTL GENERIC TABLE
  391. } GEN_TABLE, *PGEN_TABLE;
  392. //
  393. // A guid/name is a binary guid and its corresponding printable name
  394. //
  395. typedef struct _GNAME {
  396. GUID *Guid; // binary guid
  397. PWCHAR Name; // printable name (NOT A STRING VERSION OF THE GUID!)
  398. } GNAME, *PGNAME;
  399. typedef struct _CONFIG_NODE CONFIG_NODE, *PCONFIG_NODE;
  400. struct _CONFIG_NODE {
  401. FRS_NODE_HEADER Header; // For memory management
  402. BOOL Consistent; // node is consistent
  403. BOOL Inbound; // TRUE if Inbound cxtion
  404. BOOL ThisComputer; // Member object for this computer
  405. ULONG DsObjectType; // Type code corresponding to the DS Object
  406. PWCHAR Dn; // fully qualified distinguished name for DS object.
  407. PWCHAR PrincName; // NT4 Account Name
  408. PWCHAR SettingsDn; // FQDN of NTDS Settings (DSA) reference for DC system volumes
  409. PWCHAR ComputerDn; // computer reference
  410. PWCHAR MemberDn; // member reference
  411. PWCHAR SetType; // Type of replica set
  412. PWCHAR DnsName; // of this member's computer object
  413. PWCHAR PartnerDnsName; // of this cxtion's partner
  414. PWCHAR Sid; // of this member's computer
  415. PWCHAR PartnerSid; // partner's sid (from member's computer)
  416. PGNAME Name; // printable name and guid
  417. PGNAME PartnerName; // printable name and guid of our partner
  418. PWCHAR PartnerDn; // distinguished name for partner
  419. PWCHAR PartnerCoDn; // partner's computer dn
  420. PCONFIG_NODE Partner; // partner's node in the tree
  421. PWCHAR Root; // Root of replicated tree
  422. PWCHAR Stage; // staging area
  423. PWCHAR Working; // working directory
  424. PWCHAR FileFilterList; // File Filter
  425. PWCHAR DirFilterList; // Directory Filter
  426. PCONFIG_NODE Peer; // address of peer in tree
  427. PCONFIG_NODE Parent; // parent in tree
  428. PCONFIG_NODE Children; // children
  429. ULONG NumChildren; // helps check the tree's linkage
  430. PSCHEDULE Schedule;
  431. ULONG ScheduleLength;
  432. ULONG FrsRsoFlags; // ATTR_FRS_FLAGS
  433. ULONG CxtionOptions; // Options on the NTDS-Connection object.
  434. // Only NTDSCONN_OPT_TWOWAY_SYNC is of interest.
  435. PWCHAR UsnChanged; // usn changed from the DS
  436. BOOL SameSite;
  437. PWCHAR EnabledCxtion; // Cxtion is disabled iff == L"FALSE"
  438. BOOL VerifiedOverlap; // Decrease cpu usage; check once
  439. };
  440. /******************************************************************************
  441. *******************************************************************************
  442. ** **
  443. ** **
  444. ** C X T I O N **
  445. ** **
  446. ** **
  447. *******************************************************************************
  448. ******************************************************************************/
  449. //
  450. // A connection
  451. //
  452. struct _OUT_LOG_PARTNER_;
  453. typedef struct _CXTION CXTION, *PCXTION;
  454. struct _CXTION {
  455. FRS_NODE_HEADER Header; // memory management
  456. ULONG State; // Incore state
  457. ULONG Flags; // misc flags
  458. BOOL Inbound; // TRUE if inbound cxtion *
  459. BOOL JrnlCxtion; // TRUE if this Cxtion struct is for the local NTFS Journal
  460. PGNAME Name; // Cxtion name/guid from the DS *
  461. PGNAME Partner; // Partner's name/guid from the DS *
  462. PWCHAR PartnerDnsName; // partner's DNS name from the DS *
  463. PWCHAR PartnerPrincName; // partner's server principle name *
  464. PWCHAR PartnerSid; // partner's sid (string) *
  465. PWCHAR PartSrvName; // Partner's server name
  466. ULONG PartnerAuthLevel; // Authentication level *
  467. PGEN_TABLE VVector; // partner's version vector
  468. PGEN_TABLE CompressionTable; // partner's list of supported compression formats.
  469. PSCHEDULE Schedule; // schedule *
  470. DWORD Options; // options attribute from DS *
  471. DWORD Priority; // options attribute from DS *
  472. ULONG TerminationCoSeqNum;// The Seq Num of most recent Termination CO inserted.
  473. PCOMMAND_SERVER VvJoinCs; // command server for vvjoins
  474. struct _COMMAND_PACKET *JoinCmd; // check join status; rejoin if needed
  475. // NULL == no delayed cmd outstanding
  476. ULONGLONG LastJoinTime; // The time of the last successful join on this cxtion.
  477. GUID JoinGuid; // Unique id for this join
  478. GUID ReplicaVersionGuid; // partner's originator guid
  479. DWORD CommQueueIndex; // Comm layer queue for sending pkts
  480. DWORD ChangeOrderCount; // remote/control change orders pending
  481. PGEN_TABLE CoeTable; // table of idle change orders
  482. struct _COMMAND_PACKET *CommTimeoutCmd; // Timeout (waitable timer) packet
  483. DWORD UnjoinTrigger; // DBG force unjoin in # remote cos
  484. DWORD UnjoinReset; // reset force unjoin trigger
  485. PFRS_QUEUE CoProcessQueue; // If non-null then Unidle the queue when
  486. // JOIN succeeds or fails.
  487. ULONG CommPkts; // Number of comm pkts
  488. ULONG Penalty; // Penalty in Milliseconds
  489. PCOMM_PACKET ActiveJoinCommPkt; // Don't flood Q w/many join pkts
  490. ULONG PartnerMajor; // From comm packet
  491. ULONG PartnerMinor; // From comm packet
  492. struct _OUT_LOG_PARTNER_ *OLCtx; // Outbound Log Context for this connection.
  493. struct _HASHTABLEDATA_REPLICACONN *PerfRepConnData; // PERFMON counter data structure
  494. };
  495. //
  496. // Cxtion State
  497. //
  498. // A connection is initially created in the INIT state and then goes to
  499. // the UNJOINED state. From there it goes to the STARTING state
  500. // when a StartJoin request is sent to the inbound log subsystem. When
  501. // inlog starts the request it advances the state to SCANNING. When it
  502. // has scanned the inbound log for the replica set and has requeued any
  503. // change orders from this inbound partner's connection it advances the
  504. // state to SENDJOIN. The Replica subsystem then picks it up as part of
  505. // its retry path, does any one time init, and sends the Join request to
  506. // the inbound partner and advances to WAITJOIN.
  507. //
  508. // Once the join request is completed the state goes to JOINED if it succeeded
  509. // or to UNJOINED if it failed. Always use SetCxtionState() to set a new state.
  510. //
  511. // Note: It must go to one of these two states because the change order accept
  512. // logic in the inbound log process may be blocked on a retry change order for
  513. // this connection because it is waiting for the join to finish before it issues
  514. // the CO.
  515. //
  516. typedef enum _CXTION_STATE {
  517. CxtionStateInit = 0, // Newly allocated
  518. CxtionStateUnjoined, // Not joined to partner
  519. CxtionStateStart, // Inbound Partner has requested join
  520. CxtionStateStarting, // Starting the join
  521. CxtionStateScanning, // Scanning the inbound log
  522. CxtionStateSendJoin, // Scan complete, send join request to partner
  523. CxtionStateWaitJoin, // Sent request, waiting for partner's reply
  524. CxtionStateJoined, // Joined with partner
  525. CxtionStateUnjoining, // Draining remote co's through retry
  526. CxtionStateDeleted, // Cxtion has been deleted
  527. CXTION_MAX_STATE
  528. } CXTION_STATE;
  529. extern PCHAR CxtionStateNames[CXTION_MAX_STATE];
  530. //
  531. // Cxtion flags
  532. // Cxtion flags are divided in two parts. Ones that are in the upper short part
  533. // of the DWORD and the ones that are in the lower short part of the DWORD.
  534. // Following lower short flags are volatile and are not saved in the DB.
  535. #define CXTION_FLAGS_CONSISTENT 0x00000001 // info from ds is okay
  536. #define CXTION_FLAGS_SCHEDULE_OFF 0x00000002 // schedule says stop
  537. #define CXTION_FLAGS_VOLATILE 0x00000004 // sysvol seeding cxtion; delete at unjoin
  538. #define CXTION_FLAGS_DEFERRED_JOIN 0x00000008 // join requested during unjoin
  539. #define CXTION_FLAGS_DEFERRED_UNJOIN 0x00000010 // Unjoin requested during join
  540. #define CXTION_FLAGS_TIMEOUT_SET 0x00000020 // timeout cmd on timeout queue
  541. #define CXTION_FLAGS_JOIN_GUID_VALID 0x00000040 // guid valid for networking
  542. #define CXTION_FLAGS_UNJOIN_GUID_VALID 0x00000080 // guid valid for unjoin only
  543. #define CXTION_FLAGS_PERFORM_VVJOIN 0x00000100 // Force a vvjoin
  544. #define CXTION_FLAGS_DEFERRED_DELETE 0x00000200 // deferred delete
  545. #define CXTION_FLAGS_PAUSED 0x00000400 // Used to serialize vvjoin.
  546. #define CXTION_FLAGS_HUNG_INIT_SYNC 0x00000800 // Used to detect hung init syncs.
  547. #define CXTION_FLAGS_TRIM_OUTLOG 0x00001000 // Used to trim outlog by deleting this connection.
  548. // Following upper short flags are stored in the upper short part of the
  549. // CxtionRecord->Flags field in the DB. The outlog state of the connection is
  550. // stored in the lower short part of the CxtionRecord.
  551. #define CXTION_FLAGS_INIT_SYNC 0x40000000 // Connection has not completed initial sync.
  552. #define CXTION_FLAGS_TRIGGER_SCHEDULE 0x80000000 // DB: sysvol uses a trigger schedule
  553. //
  554. // Both the OutLogPartner and Cxtion are stored in a single cxtion record.
  555. // Unfortunately, there is only one flags word. For now, the low short
  556. // belongs to the OutLogPartner->Flags and the upper short Cxtion->Flags.
  557. //
  558. #define CXTION_FLAGS_CXTION_RECORD_MASK 0xffff0000
  559. //
  560. // Volatile outbound connections need timeout protection for inactivity so
  561. // we don't accumulate staging file data if they have gone away.
  562. //
  563. #define VOLATILE_OUTBOUND_CXTION(_cxtion) \
  564. (CxtionFlagIs((_cxtion), CXTION_FLAGS_VOLATILE) && !(_cxtion)->Inbound)
  565. //
  566. // The replica lock protects the filter lists (for now)
  567. //
  568. #define LOCK_REPLICA(_replica_) \
  569. DPRINT1(5, "LOCK_REPLICA: "#_replica_":%08x\n", PtrToUlong(_replica_)); \
  570. EnterCriticalSection(&(_replica_)->ReplicaLock);
  571. #define UNLOCK_REPLICA(_replica_) \
  572. LeaveCriticalSection(&(_replica_)->ReplicaLock); \
  573. DPRINT1(5, "UNLOCK_REPLICA: "#_replica_":%08x\n", PtrToUlong(_replica_));
  574. //
  575. // The table lock protects the gen table of cxtions and
  576. // the cxtion's join guid and state.
  577. //
  578. #define LOCK_CXTION_TABLE(_replica) \
  579. ReplicaStateTrace2(5, DEBSUB, __LINE__, _replica, "LOCK_CXTION_TABLE"); \
  580. GTabLockTable((_replica)->Cxtions);
  581. #define UNLOCK_CXTION_TABLE(_replica) \
  582. GTabUnLockTable((_replica)->Cxtions); \
  583. ReplicaStateTrace2(5, DEBSUB, __LINE__, _replica, "UNLOCK_CXTION_TABLE");
  584. //
  585. // The table lock protects the gen table of change orders active on this cxtion
  586. // so they can be sent thru retry if the cxtion unjoins.
  587. //
  588. #define LOCK_CXTION_COE_TABLE(_replica, _cxtion_) \
  589. CxtionStateTrace(5, DEBSUB, __LINE__, _cxtion_, _replica, 0, "LOCK_CXTION_COE_TABLE");\
  590. GTabLockTable((_cxtion_)->CoeTable);
  591. #define UNLOCK_CXTION_COE_TABLE(_replica, _cxtion_) \
  592. CxtionStateTrace(5, DEBSUB, __LINE__, _cxtion_, _replica, 0, "UNLOCK_CXTION_COE_TABLE");\
  593. GTabUnLockTable((_cxtion_)->CoeTable);
  594. //
  595. // The table lock protects the gen table of replicas
  596. //
  597. #define LOCK_REPLICA_TABLE(_replica_table_) \
  598. DPRINT1(5, "LOCK_REPLICA_TABLE: "#_replica_table_":%08x\n", PtrToUlong(_replica_table_)); \
  599. GTabLockTable(_replica_table_);
  600. #define UNLOCK_REPLICA_TABLE(_replica_table_) \
  601. GTabUnLockTable(_replica_table_); \
  602. DPRINT1(5, "UNLOCK_REPLICA_TABLE: "#_replica_table_":%08x\n", PtrToUlong(_replica_table_));
  603. //
  604. // The remote change order count is used when transitioning the cxtion
  605. // from unjoining to unjoined. The transition doesn't occur until the
  606. // count goes to 0. Internal join requests are ignored during this time.
  607. // Join requests initiated by our partner are deferred until the cxtion
  608. // is unjoined. The count goes to 0 when all of the remote change orders
  609. // have been taken through the retire or retry path.
  610. //
  611. #define INCREMENT_CXTION_CHANGE_ORDER_COUNT(_replica_, _cxtion_) \
  612. InterlockedIncrement(&((_cxtion_)->ChangeOrderCount)); \
  613. CXTION_STATE_TRACE(3, (_cxtion_), (_replica_), (_cxtion_)->ChangeOrderCount, "N, CXT CO CNT INC");
  614. //
  615. // Synchronize with LOCK_CXTION_TABLE()
  616. //
  617. #define CHECK_CXTION_UNJOINING(_replica_, _cxtion_) \
  618. if (!(_cxtion_)->ChangeOrderCount && \
  619. CxtionStateIs(_cxtion_, CxtionStateUnjoining)) { \
  620. RcsSubmitReplicaCxtion(_replica_, _cxtion_, CMD_UNJOIN); \
  621. }
  622. #define DECREMENT_CXTION_CHANGE_ORDER_COUNT(_replica_, _cxtion_) \
  623. InterlockedDecrement(&((_cxtion_)->ChangeOrderCount)); \
  624. CXTION_STATE_TRACE(3, (_cxtion_), (_replica_), (_cxtion_)->ChangeOrderCount, "N, CXT CO CNT DEC"); \
  625. CHECK_CXTION_UNJOINING(_replica_, _cxtion_);
  626. //
  627. // Initialize the cxtion Guid, Cxtion ptr and the Join Guid for this CO.
  628. // Also increment the CO count for the Cxtion.
  629. //
  630. #define INIT_LOCALCO_CXTION_AND_COUNT(_Replica_, _Coe_) \
  631. \
  632. LOCK_CXTION_TABLE(_Replica_); \
  633. (_Coe_)->Cmd.CxtionGuid = (_Replica_)->JrnlCxtionGuid; \
  634. (_Coe_)->Cxtion = GTabLookupNoLock((_Replica_)->Cxtions, \
  635. &(_Coe_)->Cmd.CxtionGuid, \
  636. NULL); \
  637. if ((_Coe_)->Cxtion != NULL) { \
  638. INCREMENT_CXTION_CHANGE_ORDER_COUNT(_Replica_, (_Coe_)->Cxtion); \
  639. (_Coe_)->JoinGuid = (_Coe_)->Cxtion->JoinGuid; \
  640. } else { \
  641. DPRINT(4, "++ Cxtion Guid lookup for Jrnl returned Null. Count unchanged.\n");\
  642. } \
  643. UNLOCK_CXTION_TABLE(_Replica_);
  644. //
  645. // Translate the CxtionGuid to a ptr and increment the Cxtion ChangeOrderCount.
  646. //
  647. #define ACQUIRE_CXTION_CO_REFERENCE(_Replica_, _Coe_) \
  648. FRS_ASSERT((_Coe_)->Cxtion == NULL); \
  649. LOCK_CXTION_TABLE(_Replica_); \
  650. (_Coe_)->Cxtion = GTabLookupNoLock((_Replica_)->Cxtions, \
  651. &(_Coe_)->Cmd.CxtionGuid, \
  652. NULL); \
  653. if ((_Coe_)->Cxtion != NULL) { \
  654. if (CxtionFlagIs((_Coe_)->Cxtion, CXTION_FLAGS_JOIN_GUID_VALID)) { \
  655. INCREMENT_CXTION_CHANGE_ORDER_COUNT(_Replica_, (_Coe_)->Cxtion); \
  656. } else { \
  657. CXTION_STATE_TRACE(3, (_Coe_)->Cxtion, (_Replica_), (_Coe_)->Cxtion->ChangeOrderCount, "N, CXT CO CNT INVALID JOIN"); \
  658. (_Coe_)->Cxtion = NULL; \
  659. } \
  660. } else { \
  661. DPRINT(4, "++ Cxtion Guid lookup returned Null. Count unchanged.\n"); \
  662. } \
  663. UNLOCK_CXTION_TABLE(_Replica_);
  664. //
  665. // Initialize ONLY the cxtion Guid and the Join Guid for this CO.
  666. // Leave the CO Cxtion ptr alone.
  667. //
  668. #define INIT_LOCALCO_CXTION_GUID(_Replica_, _Coe_) \
  669. { \
  670. PCXTION TCxtion; \
  671. LOCK_CXTION_TABLE(_Replica_); \
  672. (_Coe_)->Cmd.CxtionGuid = (_Replica_)->JrnlCxtionGuid; \
  673. TCxtion = GTabLookupNoLock((_Replica_)->Cxtions, \
  674. &(_Coe_)->Cmd.CxtionGuid, \
  675. NULL); \
  676. if (TCxtion != NULL) { \
  677. (_Coe_)->JoinGuid = TCxtion->JoinGuid; \
  678. } \
  679. UNLOCK_CXTION_TABLE(_Replica_); \
  680. }
  681. //
  682. // Release the CO count for this cxtion. A common code fragment on error path.
  683. //
  684. #define DROP_CO_CXTION_COUNT(_Replica_, _Coe_, _WStatus_) \
  685. if ((_WStatus_) != ERROR_SUCCESS) { \
  686. DPRINT1(0, "++ ERROR - ChangeOrder insert failed: %d\n", (_WStatus_)); \
  687. } \
  688. LOCK_CXTION_TABLE(_Replica_); \
  689. if ((_Coe_)->Cxtion) { \
  690. DECREMENT_CXTION_CHANGE_ORDER_COUNT((_Replica_), (_Coe_)->Cxtion); \
  691. } \
  692. UNLOCK_CXTION_TABLE(_Replica_); \
  693. (_Coe_)->Cxtion = NULL;
  694. /*
  695. VOID
  696. SetCxtionState(
  697. PCXTION _cxtion_,
  698. ULONG _state_
  699. )
  700. Defines new connection state.
  701. */
  702. #define SetCxtionState(_cxtion_, _state_) \
  703. SetCxtionStateTrace(3, DEBSUB, __LINE__, _cxtion_, _state_); \
  704. (_cxtion_)->State = _state_;
  705. /*
  706. VOID
  707. GetCxtionState(
  708. PCXTION _cxtion_
  709. )
  710. returns connection state.
  711. */
  712. #define GetCxtionState(_cxtion_) ((_cxtion_)->State)
  713. /*
  714. PCHAR
  715. GetCxtionStateName(
  716. PCXTION _c_
  717. )
  718. returns connection state name.
  719. */
  720. #define GetCxtionStateName(_c_) \
  721. (CxtionStateNames[GetCxtionState(_c_)] == NULL) \
  722. ? "<null>" \
  723. : CxtionStateNames[GetCxtionState(_c_)]
  724. /*
  725. BOOL
  726. CxtionStateIs(
  727. PCXTION _x_,
  728. ULONG _Flag_
  729. )
  730. Test connection state.
  731. */
  732. #define CxtionStateIs(_x_, _state_) ((_x_)->State == _state_)
  733. /*
  734. BOOL
  735. CxtionFlagIs(
  736. PCXTION _x_,
  737. ULONG _Flag_
  738. )
  739. Test flag state.
  740. */
  741. #define CxtionFlagIs(_x_, _Flag_) BooleanFlagOn((_x_)->Flags, _Flag_)
  742. /*
  743. VOID
  744. SetCxtionFlag(
  745. PCXTION _x_,
  746. ULONG _Flag_
  747. )
  748. Set flag state.
  749. */
  750. #define SetCxtionFlag(_x_, _Flag_) SetFlag((_x_)->Flags, _Flag_)
  751. /*
  752. VOID
  753. ClearCxtionFlag(
  754. PCXTION _x_,
  755. ULONG _Flag_
  756. )
  757. Set flag state.
  758. */
  759. #define ClearCxtionFlag(_x_, _Flag_) ClearFlag((_x_)->Flags, _Flag_)
  760. /******************************************************************************
  761. *******************************************************************************
  762. ** **
  763. ** **
  764. ** O U T L O G P A R T N E R **
  765. ** **
  766. ** **
  767. *******************************************************************************
  768. ******************************************************************************/
  769. //
  770. // The following state is kept for each outbound partner in the configuration.
  771. // It tracks our current output change order state with respect to the partner.
  772. //
  773. // The max number of change orders outstanding for any one partner is limited
  774. // by the ACK_VECTOR_SIZE (number of bits). This must be a power of 2.
  775. // It is defined in schema.h because it is saved in the connection record.
  776. //
  777. // There are two types of Outbound COs, Normal and Directed. A Normal CO is
  778. // sent to all registered outbound partners. A Directed CO is sent to a single
  779. // partner as specified by the ConnectionGuid in the CO.
  780. //
  781. // A given outbound partner can be in one of two modes, Normal and VVJoined.
  782. // In Normal mode the partner is sent all normal COs and any directed
  783. // COs addressed to it. In VVJoined mode the partner is only sent Directed COs.
  784. // Normal COs are held until the partner returns to Normal mode. The
  785. // Normal mode outlog sequence number to continue from is saved in
  786. // COTxNormalModeSave while the partner is in VV Join mode. The current mode
  787. // for the partner is kept in OLP_FLAGS_VVJOIN_MODE. This is saved in the
  788. // DB so a VVJOIN operation can continue across schedule interruptions and
  789. // machine crashes.
  790. //
  791. typedef struct _OUT_LOG_PARTNER_ {
  792. FRS_NODE_HEADER Header; // Memory alloc
  793. LIST_ENTRY List; // Link on the change order set list. (DONT MOVE)
  794. ULONG Flags; // misc state flags. see below.
  795. ULONG State; // Current state of this outbound partner.
  796. ULONGLONG AckVersion; // Ack vector version number (GMT of last reset).
  797. SINGLE_LIST_ENTRY SaveList; // The link for the DB save list.
  798. ULONG COLxRestart; // Restart point for Leading change order index.
  799. ULONG COLxVVJoinDone; // COLx where VVJoin Finished and was rolled back.
  800. ULONG COLx; // Leading change order index / sequence number.
  801. ULONG COTx; // Trailing change order index / sequence number.
  802. ULONG COTxLastSaved; // COTx value last saved in DB.
  803. ULONG COTxNormalModeSave;// Saved Normal Mode COTx while in VV Join Mode.
  804. ULONG COTslot; // Slot in Ack Vector corresponding to COTx.
  805. ULONG OutstandingCos; // The current number of change orders outstanding.
  806. ULONG OutstandingQuota; // The maximum number of COs outstanding.
  807. ULONG AckVector[ACK_VECTOR_LONGS]; // The partner ack vector.
  808. PCXTION Cxtion; // The partner connection. Has Guid and VVector.
  809. PQHASH_TABLE MustSendTable; // Tracks COx of Files we must send when skipping earlier duplicates.
  810. } OUT_LOG_PARTNER, *POUT_LOG_PARTNER;
  811. //
  812. // States for the outbound log partner.
  813. //
  814. #define OLP_INITIALIZING 0 // The partner state is initing.
  815. #define OLP_UNJOINED 1 // The partner is not joined.
  816. #define OLP_ELIGIBLE 2 // The partner can accept further COs
  817. #define OLP_STANDBY 3 // The partner is ready to join the eligible list.
  818. #define OLP_AT_QUOTA 4 // The partner is at quota for for outstanding COs.
  819. #define OLP_INACTIVE 5 // The partner is not accepting change orders.
  820. // We could still get late ACKs from this partner.
  821. #define OLP_ERROR 6 // The partner is in an Error state.
  822. #define OLP_MAX_STATE 6 // The partner is in an Error state.
  823. //
  824. // Flags word definitions. (Saved in Flags in Cxtion table record in DB)
  825. //
  826. // Following lower short flags are stored in the lower short part of the
  827. // CxtionRecord->Flags field in the DB. The Cxtion->Flags are stored in the
  828. // upper short part of the CxtionRecord.
  829. //
  830. #define OLP_FLAGS_ENABLED_CXTION 0x00000001 // Enabled-Connection from NTDS-Connection
  831. #define OLP_FLAGS_GENERATED_CXTION 0x00000002 // Generated-Connection from NTDS-Connection
  832. #define OLP_FLAGS_VVJOIN_MODE 0x00000004 // Connection is in VV JOIN Mode.
  833. #define OLP_FLAGS_LOG_TRIMMED 0x00000008 // Deleted COs for log destined for this Partner.
  834. #define OLP_FLAGS_REPLAY_MODE 0x00000010 // Connection in replay mode.
  835. #define OLP_FLAGS_OPT_VVJOIN_MODE 0x00000020 // Connection in optimized vvjoin mode.
  836. //
  837. // Both the OutLogPartner and Cxtion are stored in a single cxtion record.
  838. // Unfortunately, there is only one flags word. For now, the low short
  839. // belongs to the OutLogPartner->Flags and the upper short Cxtion->Flags.
  840. //
  841. #define OLP_FLAGS_CXTION_RECORD_MASK 0x0000ffff
  842. #define WaitingToVVJoin(_olp_) (((_olp_)->COLx == 0) && ((_olp_)->COTx == 0))
  843. #define InVVJoinMode(_olp_) (BooleanFlagOn((_olp_)->Flags, OLP_FLAGS_VVJOIN_MODE))
  844. #define InOptVVJoinMode(_olp_) (BooleanFlagOn((_olp_)->Flags, OLP_FLAGS_OPT_VVJOIN_MODE))
  845. #define InReplayMode(_olp_) (BooleanFlagOn((_olp_)->Flags, OLP_FLAGS_REPLAY_MODE))
  846. //
  847. // Macro to update state field of an Outbound log partner.
  848. //
  849. #define SET_OUTLOG_PARTNER_STATE(_Partner_, _state_) \
  850. { \
  851. DPRINT3(4, ":X: OutLog Partner state change from %s to %s for %ws\n", \
  852. OLPartnerStateNames[(_Partner_)->State], \
  853. OLPartnerStateNames[(_state_)], \
  854. (_Partner_)->Cxtion->Name->Name); \
  855. (_Partner_)->State = (_state_); \
  856. }
  857. //
  858. // Mark this outbound log partner as inactive and put it on the inactive list.
  859. //
  860. #define SET_OUTLOG_PARTNER_INACTIVE(_Replica_, _OutLogPartner_) \
  861. FrsRemoveEntryList(&((_OutLogPartner_)->List)); \
  862. SET_OUTLOG_PARTNER_STATE((_OutLogPartner_), OLP_INACTIVE); \
  863. InsertTailList(&((_Replica_)->OutLogInActive), &((_OutLogPartner_)->List));
  864. //
  865. // Mark this outbound log AVWRAPed partner as AT_QUOTA and put it on the active list.
  866. //
  867. #define SET_OUTLOG_PARTNER_AVWRAP(_Replica_, _OutLogPartner_) \
  868. FrsRemoveEntryList(&((_OutLogPartner_)->List)); \
  869. SET_OUTLOG_PARTNER_STATE((_OutLogPartner_), OLP_AT_QUOTA); \
  870. InsertTailList(&((_Replica_)->OutLogActive), &((_OutLogPartner_)->List)); \
  871. DPRINT3(1, "AVWRAP on OutLog partner %08x on Replica %08x, %ws\n", \
  872. _OutLogPartner_, _Replica_, (_Replica_)->ReplicaName->Name);
  873. //
  874. // Mark this outbound log partner as AT_QUOTA and put it on the active list.
  875. //
  876. #define SET_OUTLOG_PARTNER_AT_QUOTA(_Replica_, _OutLogPartner_) \
  877. FrsRemoveEntryList(&((_OutLogPartner_)->List)); \
  878. SET_OUTLOG_PARTNER_STATE((_OutLogPartner_), OLP_AT_QUOTA); \
  879. InsertTailList(&((_Replica_)->OutLogActive), &((_OutLogPartner_)->List));
  880. //
  881. // Mark this outbound log partner as UNJOINED and put it on the inactive list.
  882. //
  883. #define SET_OUTLOG_PARTNER_UNJOINED(_Replica_, _OutLogPartner_) \
  884. FrsRemoveEntryList(&((_OutLogPartner_)->List)); \
  885. SET_OUTLOG_PARTNER_STATE((_OutLogPartner_), OLP_UNJOINED); \
  886. InsertTailList(&((_Replica_)->OutLogInActive), &((_OutLogPartner_)->List));
  887. //
  888. // Macros to access AckVector.
  889. //
  890. #define ResetAckVector(_P_) \
  891. (_P_)->OutstandingCos = 0; \
  892. (_P_)->COTslot = 1; \
  893. GetSystemTimeAsFileTime((PFILETIME)&(_P_)->AckVersion); \
  894. ZeroMemory((_P_)->AckVector, ACK_VECTOR_BYTES);
  895. #define AVSlot(_COx_, _P_) \
  896. ((((_COx_) - (_P_)->COTx) + (_P_)->COTslot) & (ACK_VECTOR_SIZE-1))
  897. #define ClearAVBit(_COx_, _P_) { \
  898. ULONG _bit_ = AVSlot((_COx_), (_P_)); \
  899. PULONG _avw_ = &((_P_)->AckVector[ _bit_ >> 5]); \
  900. *_avw_ &= ~(1 << (_bit_ & 31)); \
  901. }
  902. #define SetAVBit(_COx_, _P_) { \
  903. ULONG _bit_ = AVSlot((_COx_), (_P_)); \
  904. PULONG _avw_ = &((_P_)->AckVector[ _bit_ >> 5]); \
  905. *_avw_ |= (1 << (_bit_ & 31)); \
  906. }
  907. #define ReadAVBitBySlot(_Slotx_, _P_) \
  908. ((((_P_)->AckVector[ ((_Slotx_) >> 5) & ACK_VECTOR_LONG_MASK]) >> \
  909. ((_Slotx_) & 31)) & 1)
  910. #define ClearAVBitBySlot(_Slotx_, _P_) \
  911. (((_P_)->AckVector[ ((_Slotx_) >> 5) & ACK_VECTOR_LONG_MASK]) &= \
  912. ~(1 << ((_Slotx_) & 31)) )
  913. #define ReadAVBit(_COx_, _P_) \
  914. ((((_P_)->AckVector[ (AVSlot((_COx_), (_P_))) >> 5]) >> \
  915. ((AVSlot((_COx_), (_P_))) & 31)) & 1)
  916. //
  917. // If the trailing index minus one equals the leading index modulo the AV size
  918. // then the vector is full and we can't issue the next change order until the
  919. // trailing index advances.
  920. //
  921. #define AVWrapped(_P_) ((((_P_)->COTx-1) & (ACK_VECTOR_SIZE-1) ) == \
  922. (((_P_)->COLx) & (ACK_VECTOR_SIZE-1) ))
  923. //
  924. // Test to see if a given outlog sequence number is outside the range of the
  925. // current Ack Vector window.
  926. //
  927. #define SeqNumOutsideAVWindow(_sn_, _P_) \
  928. (((_sn_) < ((_P_)->COTx )) || \
  929. ((_sn_) > ((_P_)->COLx + (ACK_VECTOR_SIZE-1))))
  930. /******************************************************************************
  931. *******************************************************************************
  932. ** **
  933. ** **
  934. ** R E P L I C A S E T **
  935. ** **
  936. ** **
  937. *******************************************************************************
  938. ******************************************************************************/
  939. //
  940. // An instantiation of a replica set on a machine
  941. //
  942. //
  943. // A Guid and VSN for the version vector. The Vsn is valid iff
  944. // ValidVsn is TRUE.
  945. //
  946. typedef struct _GVSN {
  947. ULONGLONG Vsn;
  948. GUID Guid;
  949. } GVSN, *PGVSN;
  950. //
  951. // The version vector is also responsible for ordering change orders to the
  952. // outbound log. The ordering is maintained by keeping a list of change
  953. // order retire slots anchored by the version vector entry in the version
  954. // vector table. Hence, the version vector will no longer use the GVSN as
  955. // the entry in the version vector. BUT the outbound version vector
  956. // continues to use the GVSN as the version vector entry. This will only
  957. // work if GVSN is the first field in a VV_ENTRY.
  958. //
  959. struct _CHANGE_ORDER_ENTRY_;
  960. typedef struct _VV_ENTRY {
  961. GVSN GVsn; // MUST BE FIRST
  962. LIST_ENTRY ListHead;
  963. ULONG CleanUpFlags;
  964. } VV_ENTRY, *PVV_ENTRY;
  965. #define VV_ENTRY_RETIRE_ACTIVE 0x00000001
  966. #define VV_RETIRE_SLOT_FLAG_OUT_OF_ORDER 0x00000001
  967. typedef struct _VV_RETIRE_SLOT {
  968. LIST_ENTRY Link;
  969. ULONGLONG Vsn;
  970. ULONG CleanUpFlags;
  971. ULONG RetireSlotFlags;
  972. struct _CHANGE_ORDER_ENTRY_ *ChangeOrder;
  973. } VV_RETIRE_SLOT, *PVV_RETIRE_SLOT;
  974. //
  975. // The following struct defines the common information related to a given
  976. // replica set. This is reference by all threads using the replica set.
  977. // Put this struct into a Generic Table indexed by GUID.
  978. // A machine can have several members of the same replica set. The member's
  979. // guid is used to identify the replica set.
  980. //
  981. struct _COMMAND_PACKET;
  982. struct _VOLUME_MONITOR_ENTRY;
  983. typedef struct _QHASH_TABLE_ QHASH_TABLE, *PQHASH_TABLE;
  984. typedef struct _REPLICA {
  985. FRS_NODE_HEADER Header; // memory management
  986. CRITICAL_SECTION ReplicaLock; // protects filter list (for now)
  987. ULONG ReferenceCount;
  988. ULONG CnfFlags; // From the config record
  989. ULONG ReplicaSetType; // Type of replica set
  990. ULONG FrsRsoFlags; // From ATTR_FRS_FLAGS in ntfrsReplicaSet object.
  991. BOOL Consistent; // replica is consistent
  992. BOOL IsOpen; // database table is open
  993. BOOL IsJournaling; // journal has been started
  994. BOOL IsAccepting; // accepting comm requests
  995. BOOL NeedsUpdate; // needs updating in the database
  996. BOOL IsSeeding; // Seeding thread is deployed
  997. BOOL IsSysvolReady; // SysvolReady is set to 1
  998. LIST_ENTRY ReplicaList; // Link all replicas together
  999. ULONG ServiceState; // stop, started, ...
  1000. FRS_ERROR_CODE FStatus; // error
  1001. PFRS_QUEUE Queue; // controlled by the command server
  1002. PGNAME ReplicaName; // Set name/Server guid from the DS
  1003. ULONG ReplicaNumber; // Internal id (name)
  1004. PGNAME MemberName; // Member name/guid from the DS
  1005. PGNAME SetName; // Set/guid name from the DS
  1006. GUID *ReplicaRootGuid; // guid assigned to Root dir
  1007. GUID ReplicaVersionGuid; // originator guid for version vector
  1008. PSCHEDULE Schedule; // schedule
  1009. PGEN_TABLE VVector; // Version vector
  1010. PGEN_TABLE OutlogVVector; // Version vector for records in outlog.
  1011. PGEN_TABLE Cxtions; // in/outbound cxtions
  1012. PWCHAR Root; // Root path
  1013. PWCHAR Stage; // Staging path
  1014. PWCHAR NewStage; // This maps to the current staging path in the
  1015. // DS. NewStage will be the one written to
  1016. // the config record but Stage will be used until
  1017. // next reboot.
  1018. PWCHAR Volume; // Volume???
  1019. ULONGLONG MembershipExpires;// membership tombstone
  1020. ULONGLONG PreInstallFid; // For journal filtering.
  1021. TABLE_CTX ConfigTable; // Db table context
  1022. FRS_LIST ReplicaCtxListHead; // Links all open contexts on this replica set.
  1023. PWCHAR FileFilterList; // Raw file filter
  1024. PWCHAR FileInclFilterList; // Raw file inclusion filter
  1025. PWCHAR DirFilterList; // Raw directory filter
  1026. PWCHAR DirInclFilterList; // Raw directory inclusion filter
  1027. LIST_ENTRY FileNameFilterHead; // Head of file name exclusion filter list.
  1028. LIST_ENTRY FileNameInclFilterHead; // Head of file name inclusion filter list.
  1029. LIST_ENTRY DirNameFilterHead; // Head of directory name filter list.
  1030. LIST_ENTRY DirNameInclFilterHead; // Head of directory name Inclusion filter list.
  1031. PQHASH_TABLE NameConflictTable; // Sequence COs using the same file name.
  1032. LONG InLogRetryCount; // Count of number CO needing a Retry.
  1033. ULONG InLogSeqNumber; // The last sequence number used in Inlog
  1034. //
  1035. //
  1036. // The inlog retry table tracks which retry change orders are currently
  1037. // active so we don't reissue the same change order until current
  1038. // invocation completes. This can happen when the system gets backed up
  1039. // and the change order retry thread kicks off again to issue retry COs
  1040. // before the last batch are able to finish. This state could be kept in
  1041. // the Inlog record but then it means extra writes to the DB.
  1042. // The sequence number is used to detect changes in the table when we don't
  1043. // have the lock. It is per-replica because it uses the change order
  1044. // sequence number of the inlog record and they aren't unique across
  1045. // replicas.
  1046. //
  1047. PQHASH_TABLE ActiveInlogRetryTable;
  1048. union {
  1049. struct {
  1050. ULONG AIRSequenceNum;
  1051. ULONG AIRSequenceNumSample;
  1052. };
  1053. ULONGLONG QuadChunkA;
  1054. };
  1055. //
  1056. // Status of sysvol seeding.
  1057. // Returned for NtFrsApi_Rpc_PromotionStatusW().
  1058. //
  1059. DWORD NtFrsApi_ServiceState;
  1060. DWORD NtFrsApi_ServiceWStatus;
  1061. #ifndef NOVVJOINHACK
  1062. DWORD NtFrsApi_HackCount; // temporary hack
  1063. #endif NOVVJOINHACK
  1064. PWCHAR NtFrsApi_ServiceDisplay;
  1065. //
  1066. // List and queues used by the InitSync Command server.
  1067. //
  1068. PGEN_TABLE InitSyncCxtionsMasterList; // sorted list of inbound connections
  1069. // used to serialize initial vvjoin.
  1070. PGEN_TABLE InitSyncCxtionsWorkingList; // subset of the InitSyncCxtionsMasterList.
  1071. // current working list.
  1072. PFRS_QUEUE InitSyncQueue; // Queue for the initsync command server.
  1073. //
  1074. // The Outbound log process state for this replica.
  1075. //
  1076. CRITICAL_SECTION OutLogLock; // protects the OutLog state
  1077. LIST_ENTRY OutLogEligible; // Eligible outbound log partners
  1078. LIST_ENTRY OutLogStandBy; // Partners ready to join eligible list
  1079. LIST_ENTRY OutLogActive; // Active outbound log partners
  1080. LIST_ENTRY OutLogInActive; // Inactive outbound log partners
  1081. ULONGLONG OutLogRepeatInterval; // Minimum Time in sec between sending update COs
  1082. PQHASH_TABLE OutLogRecordLock; // Sync access to outlog records.
  1083. PQHASH_TABLE OutLogDominantTable; // Tracks dominate COx when multiple COs for same file are present.
  1084. ULONG OutLogSeqNumber; // The last sequence number used in Outlog
  1085. ULONG OutLogJLx; // The Joint Leading Index
  1086. ULONG OutLogJTx; // The Joint Trailing Index
  1087. ULONG OutLogCOMax; // The index of the Max change order in the log.
  1088. ULONG OutLogCOMin; // The index of the Min change order in the log.
  1089. ULONG OutLogWorkState; // The output log current processing state.
  1090. struct _COMMAND_PACKET *OutLogCmdPkt; // Cmd pkt to queue when idle and have work.
  1091. PTABLE_CTX OutLogTableCtx; // Output Log Table context.
  1092. ULONG OutLogCountVVJoins; // Count of number of VVJoins in progress.
  1093. BOOL OutLogDoCleanup; // True means give log cleanup a run.
  1094. ULONG OutLogCxtionsJoined; // Count of Outlog connections that have been joined at least once.
  1095. //
  1096. // The handle to the preinstall directory
  1097. //
  1098. HANDLE PreInstallHandle;
  1099. //
  1100. // The volume journal state for this replica.
  1101. //
  1102. GUID JrnlCxtionGuid; // Used as the Cxtion Guid for Local Cos
  1103. USN InlogCommitUsn; // Our current USN Journal commit point.
  1104. //USN JournalUsn; // The Journal USN for this replica.
  1105. USN JrnlRecoveryStart; // Point to start recovery.
  1106. USN JrnlRecoveryEnd; // Point where recovery is complete.
  1107. LIST_ENTRY RecoveryRefreshList; // List of file refresh req change orders.
  1108. LIST_ENTRY VolReplicaList; // Links all REPLICA structs on volume together.
  1109. USN LastUsnRecordProcessed; // Current Journal subsystem read USN.
  1110. LONG LocalCoQueueCount; // Count of number local COs in process queue
  1111. struct _VOLUME_MONITOR_ENTRY *pVme; // Ref to the VME for this Replica.
  1112. struct _HASHTABLEDATA_REPLICASET *PerfRepSetData; // PERFMON counter data structure
  1113. } REPLICA, *PREPLICA;
  1114. //
  1115. // FRS Flags defs from FRS Replica Set Object.
  1116. //
  1117. //
  1118. // If true, Install Override tells FRS to attempt to rename an opened
  1119. // target file out of the way in order to allow installation of a new
  1120. // updated version of the file. E.G. an open .exe or .dll file would
  1121. // be treated this way. Normally (i.e. when FALSE) FRS will wait until
  1122. // it can open the target with write access. Install override only works
  1123. // if FRS can open the file for rename. This requires DELETE access to
  1124. // the file so if the target file is currently open with a sharing mode
  1125. // that denies DELETE access to other opens then FRS will not be able to
  1126. // install the updated version until the file is closed.
  1127. // *NOTE* Install Override only applies to files, not directories.
  1128. //
  1129. #define FRS_RSO_FLAGS_ENABLE_INSTALL_OVERRIDE 0x00000001
  1130. //
  1131. // If true, then remote change orders that update existing files will
  1132. // always use a pre-install file in which to build the content followed
  1133. // by a rename to insert the file into its target location in the replica
  1134. // tree. The benefit is that if FRS runs out of disk space during the
  1135. // install phase or the system crashes then a partial file (or a truncated file)
  1136. // is not left in the tree. The old content is left in place. The
  1137. // drawback of this is the need for enough disk space to hold two copies of
  1138. // the target file.
  1139. //
  1140. #define FRS_RSO_FLAGS_ENABLE_RENAME_UPDATES 0x00000002
  1141. #define REPLICA_OPTION_ENABLED(_replica_, _x_) BooleanFlagOn((_replica_)->FrsRsoFlags, (_x_))
  1142. #define OutLogAcquireLock(_Replica_) EnterCriticalSection(&((_Replica_)->OutLogLock))
  1143. #define OutLogReleaseLock(_Replica_) LeaveCriticalSection(&((_Replica_)->OutLogLock))
  1144. //
  1145. // Replica States (these track the journal states)
  1146. //
  1147. #define REPLICA_STATE_ALLOCATED 0
  1148. #define REPLICA_STATE_INITIALIZING 1
  1149. #define REPLICA_STATE_STARTING 2
  1150. #define REPLICA_STATE_ACTIVE 3
  1151. #define REPLICA_STATE_4_UNUSED 4
  1152. #define REPLICA_STATE_PAUSING 5
  1153. #define REPLICA_STATE_PAUSED 6
  1154. #define REPLICA_STATE_STOPPING 7
  1155. #define REPLICA_STATE_STOPPED 8
  1156. #define REPLICA_STATE_ERROR 9
  1157. #define REPLICA_STATE_JRNL_WRAP_ERROR 10
  1158. #define REPLICA_STATE_REPLICA_DELETED 11
  1159. #define REPLICA_STATE_MISMATCHED_VOLUME_SERIAL_NO 12
  1160. #define REPLICA_STATE_MISMATCHED_REPLICA_ROOT_OBJECT_ID 13
  1161. #define REPLICA_STATE_MISMATCHED_REPLICA_ROOT_FILE_ID 14
  1162. #define REPLICA_STATE_MISMATCHED_JOURNAL_ID 15
  1163. #define REPLICA_STATE_MAX 15
  1164. #define REPLICA_IN_ERROR_STATE(_x_) ( \
  1165. ((_x_) == REPLICA_STATE_ERROR) \
  1166. )
  1167. #define REPLICA_FSTATUS_ROOT_HAS_MOVED(_x_) ( \
  1168. ((_x_) == FrsErrorMismatchedVolumeSerialNumber) || \
  1169. ((_x_) == FrsErrorMismatchedReplicaRootObjectId) || \
  1170. ((_x_) == FrsErrorMismatchedReplicaRootFileId) \
  1171. )
  1172. #define REPLICA_STATE_NEEDS_RESTORE(_x_) ( \
  1173. (((_x_) == REPLICA_STATE_JRNL_WRAP_ERROR) && DebugInfo.EnableJrnlWrapAutoRestore) || \
  1174. ((_x_) == REPLICA_STATE_MISMATCHED_VOLUME_SERIAL_NO) || \
  1175. ((_x_) == REPLICA_STATE_MISMATCHED_REPLICA_ROOT_OBJECT_ID) || \
  1176. ((_x_) == REPLICA_STATE_MISMATCHED_REPLICA_ROOT_FILE_ID) || \
  1177. (((_x_) == REPLICA_STATE_MISMATCHED_JOURNAL_ID) && DebugInfo.EnableJrnlWrapAutoRestore) \
  1178. )
  1179. #define REPLICA_IS_ACTIVE_MASK 0x00000068 // 0110 1000
  1180. #define REPLICA_IS_ACTIVE(_Replica_) \
  1181. ((( 1 << (_Replica_)->ServiceState) & REPLICA_IS_ACTIVE_MASK) != 0)
  1182. //
  1183. // State of Replica with respect to the Output log process. (OutLogWorkState)
  1184. //
  1185. #define OL_REPLICA_INITIALIZING 0
  1186. #define OL_REPLICA_WAITING 1 // Waiting for change orders to send
  1187. #define OL_REPLICA_WORKING 2 // On the work queue sending COs
  1188. #define OL_REPLICA_STOPPING 3 // STOP request initiated.
  1189. #define OL_REPLICA_STOPPED 4 // Out Log activity on replica stopped.
  1190. #define OL_REPLICA_NOPARTNERS 5 // There are no outbound partners.
  1191. #define OL_REPLICA_ERROR 6
  1192. #define OL_REPLICA_PROC_MAX_STATE 6
  1193. //
  1194. // Macro to update state field of Outbound log processing on this replica.
  1195. //
  1196. #define SET_OUTLOG_REPLICA_STATE(_Replica_, _state_) \
  1197. { \
  1198. DPRINT3(4, ":X: OutLogWorkState change from %s to %s for %ws\n", \
  1199. OLReplicaProcStateNames[(_Replica_)->OutLogWorkState], \
  1200. OLReplicaProcStateNames[(_state_)], \
  1201. (_Replica_)->ReplicaName->Name); \
  1202. (_Replica_)->OutLogWorkState = (_state_); \
  1203. }
  1204. #define HASH_REPLICA(_p_, _TABLE_SIZE_) \
  1205. ( ( (((ULONG)_p_) >> 4) + (((ULONG)_p_) >> 16) ) & ((_TABLE_SIZE_)-1) )
  1206. #define NO_OUTLOG_PARTNERS(_Replica_) (Replica->OutLogCxtionsJoined == 0)
  1207. //
  1208. // Macros for managing the LocalCoQueueCount
  1209. //
  1210. #define INC_LOCAL_CO_QUEUE_COUNT(_R_) \
  1211. { \
  1212. LONG Temp; \
  1213. Temp = InterlockedIncrement(&(_R_)->LocalCoQueueCount); \
  1214. DPRINT1(5, "++LocalCoQueueCount now %d\n", Temp); \
  1215. }
  1216. #define DEC_LOCAL_CO_QUEUE_COUNT(_R_) \
  1217. { \
  1218. LONG Temp; \
  1219. Temp = InterlockedDecrement(&(_R_)->LocalCoQueueCount); \
  1220. DPRINT1(5, "--LocalCoQueueCount now %d\n", Temp); \
  1221. }
  1222. /******************************************************************************
  1223. *******************************************************************************
  1224. ** **
  1225. ** **
  1226. ** F R S _ T H R E A D **
  1227. ** **
  1228. ** **
  1229. *******************************************************************************
  1230. ******************************************************************************/
  1231. //
  1232. // Keep track of the threads we create
  1233. //
  1234. typedef struct _FRS_THREAD FRS_THREAD, *PFRS_THREAD;
  1235. struct _FRS_THREAD {
  1236. FRS_NODE_HEADER Header; // memory management
  1237. LIST_ENTRY List; // list of all threads
  1238. HANDLE Handle; // handle for this thread (may be NULL)
  1239. DWORD Id; // Id returned by CreateThread()
  1240. LONG Ref; // reference count
  1241. PVOID Data; // Set by FrsThreadInit parameter
  1242. ULARGE_INTEGER StartTime; // Start of rpc call
  1243. BOOL Running; // Thread is assumed to be running
  1244. PWCHAR Name; // printable name
  1245. DWORD ExitTombstone; // if non-zero then start of Tombstone period.
  1246. DWORD (*Main)(PVOID); // entry point
  1247. DWORD (*Exit)(PFRS_THREAD); // exit the thread
  1248. };
  1249. /******************************************************************************
  1250. *******************************************************************************
  1251. ** **
  1252. ** **
  1253. ** V O L U M E G U I D I N F O **
  1254. ** **
  1255. ** **
  1256. *******************************************************************************
  1257. ******************************************************************************/
  1258. typedef struct _VOLUME_INFO_NODE {
  1259. WCHAR DriveName[8]; // Drive name of the form "\\.\D:\"
  1260. ULONG VolumeSerialNumber; // VolumeSerialNumber.
  1261. } VOLUME_INFO_NODE, *PVOLUME_INFO_NODE;
  1262. /******************************************************************************
  1263. *******************************************************************************
  1264. ** **
  1265. ** **
  1266. ** G U I D / H A N D L E **
  1267. ** **
  1268. ** **
  1269. *******************************************************************************
  1270. ******************************************************************************/
  1271. typedef struct _HANDLE_LIST HANDLE_LIST, *PHANDLE_LIST;
  1272. struct _HANDLE_LIST {
  1273. PHANDLE_LIST Next; // next handle
  1274. handle_t RpcHandle; // a bound rpc handle
  1275. };
  1276. //
  1277. // Keep track of rpc handles to a specific machine (guid)
  1278. //
  1279. typedef struct _GHANDLE GHANDLE, *PGHANDLE;
  1280. struct _GHANDLE {
  1281. FRS_NODE_HEADER Header; // memory management
  1282. CRITICAL_SECTION Lock; // protects the list of handles
  1283. BOOL Ref; // Reference bit
  1284. GUID Guid; // machine guid
  1285. PHANDLE_LIST HandleList; // list of rpc handles
  1286. };
  1287. /******************************************************************************
  1288. *******************************************************************************
  1289. ** **
  1290. ** **
  1291. ** Q H A S H T A B L E **
  1292. ** **
  1293. ** **
  1294. *******************************************************************************
  1295. ******************************************************************************/
  1296. //
  1297. // The hash calc routine is called to generate the hash value of the key data
  1298. // on lookups and inserts.
  1299. //
  1300. typedef
  1301. ULONG
  1302. (NTAPI *PQHASH_CALC2_ROUTINE) (
  1303. PVOID Buf,
  1304. PULONGLONG QKey
  1305. );
  1306. //
  1307. // The keymatch routine is called to confirm an exact match on the Key Data.
  1308. //
  1309. typedef
  1310. BOOL
  1311. (NTAPI *PQHASH_KEYMATCH_ROUTINE) (
  1312. PVOID Buf,
  1313. PVOID QKey
  1314. );
  1315. //
  1316. // The free routine is called on the nodes of the large key QHash tables
  1317. // when the table is freed.
  1318. //
  1319. typedef
  1320. PVOID
  1321. (NTAPI *PQHASH_FREE_ROUTINE) (
  1322. PVOID Buf
  1323. );
  1324. //
  1325. // The Qhash entry. *** Keep the size of this a multiple of quadwords.
  1326. //
  1327. typedef struct _QHASH_ENTRY_ {
  1328. SINGLE_LIST_ENTRY NextEntry;
  1329. ULONG_PTR Flags;
  1330. ULONGLONG QKey;
  1331. ULONGLONG QData;
  1332. } QHASH_ENTRY, *PQHASH_ENTRY;
  1333. typedef struct _QHASH_TABLE_ {
  1334. FRS_NODE_HEADER Header;
  1335. ULONG BaseAllocSize;
  1336. ULONG ExtensionAllocSize;
  1337. LIST_ENTRY ExtensionListHead;
  1338. SINGLE_LIST_ENTRY FreeList;
  1339. CRITICAL_SECTION Lock;
  1340. HANDLE HeapHandle;
  1341. PGENERIC_HASH_CALC_ROUTINE HashCalc;
  1342. PQHASH_CALC2_ROUTINE HashCalc2;
  1343. PQHASH_KEYMATCH_ROUTINE KeyMatch;
  1344. PQHASH_FREE_ROUTINE HashFree;
  1345. ULONG NumberEntries;
  1346. PQHASH_ENTRY HashRowBase;
  1347. ULONG Flags;
  1348. } QHASH_TABLE, *PQHASH_TABLE;
  1349. #define QHashAcquireLock(_Table_) EnterCriticalSection(&((_Table_)->Lock))
  1350. #define QHashReleaseLock(_Table_) LeaveCriticalSection(&((_Table_)->Lock))
  1351. #define SET_QHASH_TABLE_HASH_CALC(_h_, _f_) (_h_)->HashCalc = (_f_)
  1352. #define SET_QHASH_TABLE_HASH_CALC2(_h_, _f_) (_h_)->HashCalc2 = (_f_)
  1353. #define SET_QHASH_TABLE_KEY_MATCH(_h_, _f_) (_h_)->KeyMatch = (_f_)
  1354. #define SET_QHASH_TABLE_FREE(_h_, _f_) (_h_)->HashFree = (_f_)
  1355. #define QHASH_FLAG_LARGE_KEY 0x00000001
  1356. #define SET_QHASH_TABLE_FLAG(_h_, _f_) (_h_)->Flags |= (_f_)
  1357. #define IS_QHASH_LARGE_KEY(_h_) BooleanFlagOn((_h_)->Flags, QHASH_FLAG_LARGE_KEY)
  1358. #define DOES_QHASH_LARGE_KEY_MATCH(_h_, _a_, _b_) \
  1359. (!IS_QHASH_LARGE_KEY(_h_) || ((_h_)->KeyMatch)((PVOID)(_a_), (PVOID)(_b_)))
  1360. //
  1361. // The argument function passed to QHashEnumerateTable().
  1362. //
  1363. typedef
  1364. ULONG
  1365. (NTAPI *PQHASH_ENUM_ROUTINE) (
  1366. PQHASH_TABLE Table,
  1367. PQHASH_ENTRY BeforeNode,
  1368. PQHASH_ENTRY TargetNode,
  1369. PVOID Context
  1370. );
  1371. ULONG
  1372. QHashDump (
  1373. PQHASH_TABLE Table,
  1374. PQHASH_ENTRY BeforeNode,
  1375. PQHASH_ENTRY TargetNode,
  1376. PVOID Context
  1377. );
  1378. ULONG
  1379. QHashEnumerateTable(
  1380. IN PQHASH_TABLE HashTable,
  1381. IN PQHASH_ENUM_ROUTINE Function,
  1382. IN PVOID Context
  1383. );
  1384. GHT_STATUS
  1385. QHashLookup(
  1386. IN PQHASH_TABLE HashTable,
  1387. IN PVOID ArgQKey,
  1388. OUT PULONGLONG QData,
  1389. OUT PULONG_PTR Flags
  1390. );
  1391. PQHASH_ENTRY
  1392. QHashLookupLock(
  1393. IN PQHASH_TABLE HashTable,
  1394. IN PVOID ArgQKey
  1395. );
  1396. GHT_STATUS
  1397. QHashInsert(
  1398. IN PQHASH_TABLE HashTable,
  1399. IN PVOID ArgQKey,
  1400. IN PULONGLONG QData,
  1401. IN ULONG_PTR Flags,
  1402. IN BOOL HaveLock
  1403. );
  1404. PQHASH_ENTRY
  1405. QHashInsertLock(
  1406. IN PQHASH_TABLE HashTable,
  1407. IN PVOID ArgQKey,
  1408. IN PULONGLONG QData,
  1409. IN ULONG_PTR Flags
  1410. );
  1411. GHT_STATUS
  1412. QHashUpdate(
  1413. IN PQHASH_TABLE HashTable,
  1414. IN PVOID ArgQKey,
  1415. IN PULONGLONG QData,
  1416. IN ULONG_PTR Flags
  1417. );
  1418. GHT_STATUS
  1419. QHashDelete(
  1420. IN PQHASH_TABLE HashTable,
  1421. IN PVOID ArgQKey
  1422. );
  1423. VOID
  1424. QHashDeleteLock(
  1425. IN PQHASH_TABLE HashTable,
  1426. IN PVOID ArgQKey
  1427. );
  1428. VOID
  1429. QHashDeleteByFlags(
  1430. IN PQHASH_TABLE HashTable,
  1431. IN ULONG_PTR Flags
  1432. );
  1433. VOID
  1434. QHashEmptyLargeKeyTable(
  1435. IN PQHASH_TABLE HashTable
  1436. );
  1437. /******************************************************************************
  1438. *******************************************************************************
  1439. ** **
  1440. ** **
  1441. ** V O L U M E M O N I T O R E N T R Y **
  1442. ** **
  1443. ** **
  1444. *******************************************************************************
  1445. ******************************************************************************/
  1446. //
  1447. // A volume monitor entry is allocated for each file system volume we monitor.
  1448. // When a new replica set is initialized we check the list first to see if
  1449. // we are already monitoring the journal on that volume. The reference count
  1450. // tracks the number of replica sets that are active on this volume. When
  1451. // it goes to zero we can stop monitoring the volume journal.
  1452. //
  1453. // IoActive is set TRUE when the first Read request is sent to the journal.
  1454. // From that point on the JournalReadThread will continue to post new read
  1455. // requests as the previous request completes. When the reference count
  1456. // on the volume goes to zero the StopIo flag is set TRUE and a cancel IO
  1457. // request for the volume is posted to the journal completion port. When the
  1458. // journal thread picks this up it does a CancelIo() on the volume handle.
  1459. // When the outstanding read completes (with either data or with status
  1460. // ERROR_OPERATION_ABORTED) the IoActive Flag is set false, the volume monitor
  1461. // entry is put on the VolumeMonitorStopQueue and no further read request to
  1462. // the journal is issued.
  1463. //
  1464. // Note: FSVolLabel must be AFTER FSVolInfo and MAXIMUM_VOLUME_LABEL_LENGTH
  1465. // is defined to account for WCHARS.
  1466. //
  1467. //
  1468. typedef struct _VOLUME_MONITOR_ENTRY {
  1469. FRS_NODE_HEADER Header;
  1470. LIST_ENTRY ListEntry; // MUST FOLLOW HEADER
  1471. //
  1472. // This is the list head for all replica sets on the this volume. It links
  1473. // the REPLICA structs together.
  1474. //
  1475. FRS_LIST ReplicaListHead; // List of Replica Sets on Vol.
  1476. //
  1477. // The following USNs are for managing the NTFS USN journal on the volume.
  1478. //
  1479. USN JrnlRecoveryEnd; // Point where recovery is complete.
  1480. USN CurrentUsnRecord; // USN of record currently being processed.
  1481. USN CurrentUsnRecordDone; // USN of most recent record done processing.
  1482. USN LastUsnSavePoint; // USN of last vol wide save.
  1483. USN MonitorMaxProgressUsn; // Farthest progress made in this journal.
  1484. USN JrnlReadPoint; // The current active read point for journal.
  1485. USN_JOURNAL_DATA UsnJournalData; // FSCTL_QUERY_USN_JOURNAL data at journal open.
  1486. USN MonitorProgressUsn; // Start journal from here after pause.
  1487. USN ReplayUsn; // Start journal here after replica startup request
  1488. BOOL ReplayUsnValid; // above has valid data.
  1489. //
  1490. // The FrsVsn is a USN kept by FRS and exported by all replica sets on the
  1491. // volume. It is unaffected by disk reformats and is saved in the config
  1492. // record of each replica set. At startup we use the maximum value for all
  1493. // replica sets on a given volume. The only time they might differ is when
  1494. // service on a given replica set is not started.
  1495. //
  1496. ULONGLONG FrsVsn; // Private FRS volume seq num.
  1497. CRITICAL_SECTION Lock; // To sync access to VME.
  1498. CRITICAL_SECTION QuadWriteLock; // To sync updates to quadwords.
  1499. OVERLAPPED CancelOverlap; // Overlap struct for cancel req
  1500. ULONG WStatus; // Win32 status on error
  1501. ULONG ActiveReplicas; // Num replica sets active on journal
  1502. HANDLE Event; // Event handle for pause journal.
  1503. HANDLE VolumeHandle; // The vol handle for journal.
  1504. WCHAR DriveLetter[4]; // Drive letter for this volume.
  1505. //
  1506. // A change order table is kept on each volume to track the pending
  1507. // change orders. Tracking it for each replica set would be nice but
  1508. // that approach has a problem with renames that move files or dirs
  1509. // across replica sets on the volume. If there are prior change orders
  1510. // outstanding on a parent dir (MOVEOUT) in RS-A followed by a MOVEIN on
  1511. // a child file X to RS-B we must be sure the MOVEOUT on the parent happens
  1512. // before the MOVEIN on X. Similar problems arise with a MOVEOUT of file X
  1513. // followed by a MOVEIN to a different R.S. on the same volume. We need to
  1514. // locate the pending MOVEOUT change order on the volume or ensure it is
  1515. // processed first. One list per volume solves these problems.
  1516. //
  1517. PGENERIC_HASH_TABLE ChangeOrderTable;// The Replica Change Order table.
  1518. FRS_QUEUE ChangeOrderList; // Change order processing list head.
  1519. LIST_ENTRY UpdateList; // Link for the Replica Update Process Queue.
  1520. ULONG InitTime; // Time reference for the ChangeOrderList.
  1521. //
  1522. // THe Active Inbound Change Order table holds the change order structs
  1523. // indexed by File ID. An entry in the table means that we have an
  1524. // inbound (either local or remote) change order active on this file.
  1525. //
  1526. PGENERIC_HASH_TABLE ActiveInboundChangeOrderTable;
  1527. //
  1528. // The ActiveChildren hash table is used to record the parent FID of each
  1529. // active change order. This is used to prevent a change order from starting
  1530. // on the parent while a change order is active on one or more children.
  1531. // For example if the child change order was a create and the parent change
  1532. // order was an ACL change to prevent further creates, we must ensure the
  1533. // child completes before starting the parent change order. Each entry has
  1534. // a count of the number of active children and a flag that is set if the
  1535. // change order process queue is blocked because of a pending change order
  1536. // on the parent. When the count goes to zero the queue is unblocked.
  1537. //
  1538. PQHASH_TABLE ActiveChildren;
  1539. //
  1540. // The Parent Table is a simple hash table used to keep the parent File ID
  1541. // for each file and dir in any Replica Set on the volume. It is used in
  1542. // renames to find the old parent.
  1543. //
  1544. PQHASH_TABLE ParentFidTable;
  1545. //
  1546. // The FRS Write Filter table filters out journal entries caused
  1547. // by file system write from the File Replication Service (Us) when we
  1548. // install files in the replica tree.
  1549. //
  1550. PQHASH_TABLE FrsWriteFilter;
  1551. //
  1552. // The Recovery Conflict Table contains the FIDs of files that were in
  1553. // the inbound log when we crashed. At the start of recovery the inbound
  1554. // log for the given replica set is scanned and the FIDs are entered into
  1555. // the table. During journal processing any USN records with a matching
  1556. // FID are deemed to caused by FRS so we skip the record. (This is because
  1557. // the FrsWriteFilter table was lost in the crash).
  1558. PQHASH_TABLE RecoveryConflictTable;
  1559. //
  1560. // The name space table controls the merging of USN records into COs
  1561. // that use the same file name. If a name usage conflict exists in the
  1562. // USN record stream then we can't merge the USN record into a previous
  1563. // change order on the same file.
  1564. //
  1565. PQHASH_TABLE NameSpaceTable;
  1566. ULONG StreamSequenceNumberFetched;
  1567. ULONG StreamSequenceNumberClean;
  1568. ULONG StreamSequenceNumber;
  1569. //
  1570. // THe RenOldNameTable contains the USN records of the old file names
  1571. // when a rename operation was performed. THese are used later when the
  1572. // Close record is processed for a rename to make the proper entry in the
  1573. // NameSpace Table above.
  1574. //
  1575. PQHASH_TABLE RenOldNameTable;
  1576. //
  1577. // The Filter Table contains an entry for each direcctory that is within a
  1578. // replica set on this volume. It is used to filter out Journal records for
  1579. // files/dirs that are not in a Replica set. For those Journal records that
  1580. // are in a replica set, a lookup on the parent FileId tells us which one.
  1581. //
  1582. PGENERIC_HASH_TABLE FilterTable; // THe directory filter table.
  1583. BOOL StopIo; // True means StopIo requested.
  1584. BOOL IoActive; // True means I/O active on volume.
  1585. ULONG JournalState; // Current journal state.
  1586. ULONG ReferenceCount; // Free all hash tables when it hits 0.
  1587. LONG ActiveIoRequests;// Number of Journal reads currently outstanding.
  1588. FILE_OBJECTID_BUFFER RootDirObjectId; // Object ID for volume
  1589. FILE_FS_VOLUME_INFORMATION FSVolInfo; // NT volume info.
  1590. CHAR FSVolLabel[MAXIMUM_VOLUME_LABEL_LENGTH];
  1591. } VOLUME_MONITOR_ENTRY, *PVOLUME_MONITOR_ENTRY;
  1592. #define LOCK_VME(_pVme_) EnterCriticalSection(&(_pVme_)->Lock)
  1593. #define UNLOCK_VME(_pVme_) LeaveCriticalSection(&(_pVme_)->Lock)
  1594. //
  1595. // Once the ref count goes to zero return 0 so the caller knows they didn't get it.
  1596. // Caller must check result and abort current op if RefCount is zero.
  1597. // Note: May need to move to interlocked compare an exchange if a race between
  1598. // final decrement to zero and another increment can actually occur. The VME
  1599. // memory is not actually freed but such a race with the cleanup code
  1600. // could be a problem as could execution of the cleanup code multiple times.
  1601. // Could also wrap the deal with the Vme Lock. Sigh.
  1602. //
  1603. #define AcquireVmeRef(_pVme_) \
  1604. ((_pVme_)->ReferenceCount == 0) ? \
  1605. 0 : InterlockedIncrement(&((_pVme_)->ReferenceCount))
  1606. #define ReleaseVmeRef(_pVme_) \
  1607. if (InterlockedDecrement(&((_pVme_)->ReferenceCount)) == 0) { \
  1608. DPRINT1(5, "VMEREF-- = %d\n", (_pVme_)->ReferenceCount); \
  1609. JrnlCleanupVme(_pVme_); \
  1610. } \
  1611. DPRINT1(5, "VMEREF-- = %d\n", (_pVme_)->ReferenceCount);
  1612. //
  1613. // NEW_VSN hands out new VSNs and every 'VSN_SAVE_INTERVAL' VSNs that
  1614. // are handed out, save the state in the config record. On restart we
  1615. // take the largest value and add 2*(VSN_SAVE_INTERVAL+1) to it so if a
  1616. // crash occurred we ensure that it never goes backwards.
  1617. //
  1618. VOID
  1619. JrnlNewVsn(
  1620. IN PCHAR Debsub,
  1621. IN ULONG uLineNo,
  1622. IN PVOLUME_MONITOR_ENTRY pVme,
  1623. IN OUT PULONGLONG NewVsn
  1624. );
  1625. #define NEW_VSN(_pVme_, _pResult_) \
  1626. JrnlNewVsn(DEBSUB, __LINE__, _pVme_, _pResult_)
  1627. //
  1628. // Replay Mode means we have backed up the journal read point because another
  1629. // replica set has started and needs to see some earlier records. All other
  1630. // currently active Replica Sets sharing the same journal are implicitly in
  1631. // Replay Mode, skipping all records directed at them, since they have already
  1632. // been processed.
  1633. //
  1634. // The replica set is in replay mode if the LastUsnRecordProcessed is < than the
  1635. // current USN record being processed (pVme->CurrentUsnRecord). Likewise the
  1636. // journal is in replay mode if MonitorMaxProgressUsn > CurrentUsnRecord.
  1637. //
  1638. #define REPLICA_REPLAY_MODE(_Replica_, _pVme_) \
  1639. ((_Replica_)->LastUsnRecordProcessed > (_pVme_)->CurrentUsnRecord)
  1640. #define JOURNAL_REPLAY_MODE(_pVme_) \
  1641. ((_pVme_)->MonitorMaxProgressUsn > (_pVme_)->CurrentUsnRecord)
  1642. #define CAPTURE_JOURNAL_PROGRESS(_pVme_, _pp_) \
  1643. if ((_pVme_)->MonitorProgressUsn == (USN) 0) { \
  1644. (_pVme_)->MonitorProgressUsn = (_pp_); \
  1645. }
  1646. #define CAPTURE_MAX_JOURNAL_PROGRESS(_pVme_, _pp_) \
  1647. if (!JOURNAL_REPLAY_MODE(_pVme_)) { \
  1648. (_pVme_)->MonitorMaxProgressUsn = (_pp_); \
  1649. }
  1650. #define LOAD_JOURNAL_PROGRESS(_pVme_, _alternate_pp_) \
  1651. (((_pVme_)->MonitorProgressUsn != (USN) 0) ? \
  1652. (_pVme_)->MonitorProgressUsn : (_alternate_pp_))
  1653. #define RESET_JOURNAL_PROGRESS(_pVme_) (_pVme_)->MonitorProgressUsn = (USN) 0
  1654. //
  1655. // The following macro is used to prevent quadword tearing in references
  1656. // to CurrentUsnRecordDone
  1657. //
  1658. #define UpdateCurrentUsnRecordDone(_pVme, _CurrentUsn) \
  1659. AcquireQuadLock(&((_pVme)->QuadWriteLock)); \
  1660. (_pVme)->CurrentUsnRecordDone = (_CurrentUsn); \
  1661. ReleaseQuadLock(&((_pVme)->QuadWriteLock))
  1662. //
  1663. // Journal States (these track the Replica States).
  1664. //
  1665. #define JRNL_STATE_ALLOCATED 0
  1666. #define JRNL_STATE_INITIALIZING 1
  1667. #define JRNL_STATE_STARTING 2
  1668. #define JRNL_STATE_ACTIVE 3
  1669. #define JRNL_STATE_PAUSE1 4
  1670. #define JRNL_STATE_PAUSE2 5
  1671. #define JRNL_STATE_PAUSED 6
  1672. #define JRNL_STATE_STOPPING 7
  1673. #define JRNL_STATE_STOPPED 8
  1674. #define JRNL_STATE_ERROR 9
  1675. #define JRNL_STATE_JRNL_WRAP_ERROR 10
  1676. #define JRNL_STATE_REPLICA_DELETED 11
  1677. #define JRNL_STATE_MISMATCHED_VOLUME_SERIAL_NO 12
  1678. #define JRNL_STATE_MISMATCHED_REPLICA_ROOT_OBJECT_ID 13
  1679. #define JRNL_STATE_MISMATCHED_REPLICA_ROOT_FILE_ID 14
  1680. #define JRNL_STATE_MISMATCHED_JOURNAL_ID 15
  1681. #define JRNL_STATE_MAX 15
  1682. #define JRNL_IN_ERROR_STATE(_x_) ( \
  1683. ((_x_) == JRNL_STATE_ERROR) || \
  1684. ((_x_) == JRNL_STATE_JRNL_WRAP_ERROR) \
  1685. )
  1686. #define JRNL_STATE_NEEDS_RESTORE(_x_) ( \
  1687. ((_x_) == JRNL_STATE_JRNL_WRAP_ERROR) || \
  1688. ((_x_) == JRNL_STATE_MISMATCHED_VOLUME_SERIAL_NO) || \
  1689. ((_x_) == JRNL_STATE_MISMATCHED_REPLICA_ROOT_OBJECT_ID) || \
  1690. ((_x_) == JRNL_STATE_MISMATCHED_REPLICA_ROOT_FILE_ID) || \
  1691. ((_x_) == JRNL_STATE_MISMATCHED_JOURNAL_ID) \
  1692. )
  1693. #define RSS_LIST(_state_) ReplicaServiceState[_state_].ServiceList
  1694. #define RSS_NAME(_state_) (((_state_) <= JRNL_STATE_MAX) ? \
  1695. ReplicaServiceState[_state_].Name : \
  1696. ReplicaServiceState[JRNL_STATE_ALLOCATED].Name)
  1697. //
  1698. // The loop iterator pE is of type REPLICA.
  1699. // Update the state of the journal VME and the associated replicas.
  1700. //
  1701. #define SET_JOURNAL_AND_REPLICA_STATE(_pVme_, _NewState_) \
  1702. { \
  1703. PVOLUME_MONITOR_ENTRY ___pVme = (_pVme_); \
  1704. \
  1705. DPRINT3(4, ":S: JournalState from %s to %s for %ws\n", \
  1706. RSS_NAME(___pVme->JournalState), \
  1707. RSS_NAME(_NewState_), \
  1708. ___pVme->FSVolInfo.VolumeLabel); \
  1709. ___pVme->JournalState = (_NewState_); \
  1710. ForEachListEntry( &(___pVme->ReplicaListHead), REPLICA, VolReplicaList, \
  1711. JrnlSetReplicaState(pE, (_NewState_)); \
  1712. ) \
  1713. }
  1714. #define REPLICA_ACTIVE_INLOG_RETRY_SIZE sizeof(QHASH_ENTRY)*64
  1715. #define REPLICA_NAME_CONFLICT_TABLE_SIZE sizeof(QHASH_ENTRY)*100
  1716. #define NAME_SPACE_TABLE_SIZE sizeof(QHASH_ENTRY)*100
  1717. #define RENAME_OLD_TABLE_SIZE sizeof(QHASH_ENTRY)*100
  1718. #define FRS_WRITE_FILTER_SIZE sizeof(QHASH_ENTRY)*100
  1719. #define RECOVERY_CONFLICT_TABLE_SIZE sizeof(QHASH_ENTRY)*100
  1720. #define PARENT_FILEID_TABLE_SIZE sizeof(QHASH_ENTRY)*500
  1721. #define ACTIVE_CHILDREN_TABLE_SIZE sizeof(QHASH_ENTRY)*100
  1722. #define OUTLOG_RECORD_LOCK_TABLE_SIZE sizeof(QHASH_ENTRY)*10
  1723. #define OUTLOG_DOMINANT_FILE_TABLE_SIZE sizeof(QHASH_ENTRY)*128
  1724. #define OUTLOG_MUSTSEND_FILE_TABLE_SIZE sizeof(QHASH_ENTRY)*32
  1725. #define PARTNER_NAME_TABLE_SIZE sizeof(QHASH_ENTRY)*128
  1726. #define PARTNER_CONNECTION_TABLE_SIZE sizeof(QHASH_ENTRY)*128
  1727. #define QHASH_EXTENSION_MAX sizeof(QHASH_ENTRY)*50
  1728. /******************************************************************************
  1729. *******************************************************************************
  1730. ** **
  1731. ** **
  1732. ** J B U F F E R **
  1733. ** **
  1734. ** **
  1735. *******************************************************************************
  1736. ******************************************************************************/
  1737. //
  1738. // Journal buffers are allocated in SizeOfJournalBuffer chunks.
  1739. // The first part of each buffer has a descriptor as defined below.
  1740. //
  1741. #define SizeOfJournalBuffer (4*1024)
  1742. typedef struct _JBUFFER {
  1743. FRS_NODE_HEADER Header;
  1744. LIST_ENTRY ListEntry; // MUST FOLLOW HEADER
  1745. IO_STATUS_BLOCK Iosb; // Iosb for this read.
  1746. OVERLAPPED Overlap; // Overlap struct for this I/O
  1747. HANDLE FileHandle; // File handle where I/O was done.
  1748. PVOLUME_MONITOR_ENTRY pVme; // Vol Mon Entry I/O is for.
  1749. ULONG DataLength; // Data len Returned from read.
  1750. ULONG BufferSize; // Size of buffer
  1751. PLONGLONG DataBuffer; // ptr to Buffer
  1752. ULONG WStatus; // Win32 status after async I/O req.
  1753. USN JrnlReadPoint; // Starting USN for journal read.
  1754. ULONGLONG Buffer[1]; // Buffer to put journal data.
  1755. } JBUFFER, *PJBUFFER;
  1756. #define SizeOfJournalBufferDesc (OFFSET(JBUFFER, Buffer))
  1757. /******************************************************************************
  1758. *******************************************************************************
  1759. ** **
  1760. ** **
  1761. ** T H R E A D C O M M A N D P A C K E T **
  1762. ** **
  1763. ** **
  1764. *******************************************************************************
  1765. ******************************************************************************/
  1766. // Command packets are used to request a subsystem to perform some service.
  1767. // For example the Journal sub-system uses a command packet to initialize
  1768. // journal processing for a given replica set. Another command is used
  1769. // to begin journal processing (once all the replica sets have been
  1770. // initialized. Another command is to stop journal processing on a given
  1771. // volume.
  1772. //
  1773. // The structure is derived from the NT I/O request packet structure.
  1774. //
  1775. //
  1776. // Define completion routine types for use in command packet.
  1777. //
  1778. //
  1779. // The database field descriptor is used to update selected fields in a
  1780. // database record.
  1781. //
  1782. typedef struct _DB_FIELD_DESC_ {
  1783. ULONG FieldCode; // The data field ID number (ENUM symbol)
  1784. PVOID Data; // The new data value
  1785. ULONG Length; // Data length
  1786. ULONG FStatus; // Returned stats from field update.
  1787. } DB_FIELD_DESC, *PDB_FIELD_DESC;
  1788. //
  1789. // The DB_SERVICE_REQUEST is used to pass a request to the database command
  1790. // server. It is pulled out as a seperate struct so the caller can create a
  1791. // pointer to it for easier manipulation.
  1792. //
  1793. // The TableCtx is a handle to a struct that describes what table is being
  1794. // accessed. It also contains the storage for the data record being read
  1795. // or written. Access to a pointer to this record is via the macro
  1796. // DBS_GET_RECORD_ADDRESS(DbsRequest) where DbsRequest is a ptr to the
  1797. // DB_SERVICE_REQUEST struct in the command packet.
  1798. //
  1799. // On the first access to a specific table, TableCtx is NULL. All subsequent
  1800. // accesses should return the value unchanged. The caller must cleanup by
  1801. // closing the table with a CMD_CLOSE_TABLE command packet or the DB will be
  1802. // left with open tables. For single, one time requests, set the Close
  1803. // flag in the AccessRequest field to close the table before returning.
  1804. // The close flag can also be set on the last of a series of requests to
  1805. // avoid the need to send a CMD_CLOSE_TABLE command packet.
  1806. //
  1807. // The Context used by Database service commands is the
  1808. // Config Table record. This is pointed to from the Replica Struct.
  1809. // The ConfigTableRecord has the info about the replica set.
  1810. // e.g. replica number, root path, volume ID, etc.
  1811. //
  1812. // AccessRequest specifies how the record access for reads and updates is done.
  1813. // DBS_ACCESS_BYKEY means use the index type and key value to access the record.
  1814. // DBS_ACCESS_FIRST means use the index type and access the first table record.
  1815. // DBS_ACCESS_LAST means use the index type and access the last table record.
  1816. // DBS_ACCESS_NEXT means use the index type and access the next record following
  1817. // a previous access.
  1818. // DBS_ACCESS_CLOSE means close the table after performing the operation.
  1819. // *NOTE* this close only closes the table in the database. It does not
  1820. // release the table context struct or record storage (which has
  1821. // the read data). The caller must do this by calling
  1822. // DBS_FREE_TABLECTX(DbsRequest) when the data has been consumed.
  1823. // This is different from the CMD_CLOSE_TABLE command which both
  1824. // closes the database table and frees the storage.
  1825. //
  1826. // The IndexType field specifies which index to use when accessing the table.
  1827. // It is table specific and each table has one or more indexes defined when
  1828. // the table schema was defined. An ENUM defines the code values for the
  1829. // table index.
  1830. //
  1831. // The CallContext pointer is command specific.
  1832. //
  1833. //
  1834. // WARNING: The table context is only valid within the thread that opened the
  1835. // table. If multiple DB service threads are added later we need to get a
  1836. // request back to the same thread.
  1837. //
  1838. typedef struct _DB_SERVICE_REQUEST_ {
  1839. PTABLE_CTX TableCtx; // Table context handle (NULL on first call)
  1840. PREPLICA Replica; // Replica context ptr.
  1841. ULONG TableType; // Type code for the table.
  1842. PVOID CallContext; // Call specific context
  1843. ULONG AccessRequest; // (ByKey, First, Last, Next) | Close
  1844. ULONG IndexType; // The table index to use
  1845. PVOID KeyValue; // The record key value for lookup
  1846. ULONG KeyValueLength; // The Length of the key value
  1847. FRS_ERROR_CODE FStatus; // FRS Error status
  1848. PULONG SimpleFieldIDS; // A ptr to an array of record field id numbers.
  1849. ULONG FieldCount; // Count of Field Descriptors that follow or number of SimpleFieldIDs above.
  1850. DB_FIELD_DESC Fields[1]; // One or more Field descriptors.
  1851. } DB_SERVICE_REQUEST, *PDB_SERVICE_REQUEST;
  1852. typedef
  1853. VOID
  1854. (*PCOMMAND_PACKET_COMPLETION_ROUTINE) (
  1855. IN struct _COMMAND_PACKET *CmdPkt,
  1856. IN PVOID Context
  1857. );
  1858. typedef struct _CHANGE_ORDER_ENTRY_ CHANGE_ORDER_ENTRY, *PCHANGE_ORDER_ENTRY;
  1859. typedef struct _COMMAND_PACKET COMMAND_PACKET, *PCOMMAND_PACKET;
  1860. struct _COMMAND_PACKET {
  1861. FRS_NODE_HEADER Header;
  1862. LIST_ENTRY ListEntry; // MUST FOLLOW HEADER
  1863. //
  1864. // Command is the command to the subsystem.
  1865. // Flags and control are command specific.
  1866. //
  1867. #define CMD_PKT_FLAGS_SYNC ((UCHAR) 0x01)
  1868. USHORT Command;
  1869. UCHAR Flags;
  1870. UCHAR Control;
  1871. //
  1872. // Used by the wait thread. The caller sets Timeout and TimeoutCommand.
  1873. // The wait thread owns TimeoutFileTime. and TimeoutFlags
  1874. //
  1875. #define CMD_PKT_WAIT_FLAGS_ONLIST ((USHORT) 0x0001)
  1876. #define CmdWaitFlagIs(_cmd_, _f_) FlagOn((_cmd_)->WaitFlags, _f_)
  1877. #define SetCmdWaitFlag(_cmd_, _f_) SetFlag((_cmd_)->WaitFlags, _f_)
  1878. #define ClearCmdWaitFlag(_cmd_, _f_) ClearFlag((_cmd_)->WaitFlags, _f_)
  1879. USHORT TimeoutCommand; // Caller - Disposition of pkt after timeout
  1880. USHORT WaitFlags; // Internal - flags for wait thread
  1881. DWORD Timeout; // Caller - milliseconds
  1882. LONGLONG WaitFileTime; // Internal - 100 nanoseconds
  1883. //
  1884. // If this command request is synchronous then the caller waits on the
  1885. // event handle. The submitter's Completion routine is saved in
  1886. // SavedCompletionRoutine and we put our own completion routine in the
  1887. // packet so we get the packet back and can return the status as the
  1888. // function return value. This way if the caller provides no completion
  1889. // routine the default is to free the packet but we can always return the
  1890. // status code.
  1891. //
  1892. HANDLE WaitEvent;
  1893. VOID (*SavedCompletionRoutine)(PCOMMAND_PACKET, PVOID);
  1894. //
  1895. // For scheduled commands the following parameter specifies the delay
  1896. // in milliseconds before the command is to execute. When that time
  1897. // arrives the command is queued to the target queue.
  1898. //
  1899. PFRS_QUEUE TargetQueue;
  1900. //
  1901. // Set by FrsCompleteCommand().
  1902. //
  1903. DWORD ErrorStatus;
  1904. //
  1905. // Called by FrsCompleteCommand()
  1906. //
  1907. VOID (*CompletionRoutine)(PCOMMAND_PACKET, PVOID);
  1908. //
  1909. // Passed to the CompletionRoutine
  1910. //
  1911. PVOID CompletionArg;
  1912. //
  1913. // The following parameters are based on the service that is being
  1914. // invoked. The service determines which set to use based
  1915. // on the above major and minor function codes.
  1916. //
  1917. union {
  1918. /////////////////////////////////////////////////////////////////////
  1919. // //
  1920. // Test //
  1921. // //
  1922. /////////////////////////////////////////////////////////////////////
  1923. struct {
  1924. DWORD Index;
  1925. } UnionTest;
  1926. /////////////////////////////////////////////////////////////////////
  1927. // //
  1928. // Replica Set //
  1929. // //
  1930. /////////////////////////////////////////////////////////////////////
  1931. struct {
  1932. HANDLE CompletionEvent;
  1933. PVOID From;
  1934. PVOID To;
  1935. PVOID Replica;
  1936. PVOID NewReplica;
  1937. PVOID ReplicaName;
  1938. PVOID Cxtion;
  1939. PVOID VVector;
  1940. PVOID ReplicaVv;
  1941. ULONG Timeout;
  1942. PVOID Block;
  1943. LONGLONG BlockSize;
  1944. LARGE_INTEGER FileSize;
  1945. LARGE_INTEGER FileOffset;
  1946. ULONGLONG LastJoinTime;
  1947. PVOID ChangeOrderEntry;
  1948. PVOID PartnerChangeOrderCommand;
  1949. PVOID GVsn;
  1950. PVOID ChangeOrderGuid;
  1951. ULONG ChangeOrderSequenceNumber;
  1952. PVOID JoinGuid;
  1953. PVOID JoinTime;
  1954. PVOID CommPktRcvTime;
  1955. PVOID AuthClient;
  1956. PVOID AuthName;
  1957. PVOID AuthSid;
  1958. DWORD AuthLevel;
  1959. DWORD AuthN;
  1960. DWORD AuthZ;
  1961. PVOID NewCxtion;
  1962. PVOID ReplicaVersionGuid;
  1963. ULONG COTx;
  1964. ULONG CommPkts;
  1965. PVOID Md5Digest;
  1966. PVOID PartnerChangeOrderCommandExt;
  1967. PGEN_TABLE CompressionTable;
  1968. } UnionRs;
  1969. /////////////////////////////////////////////////////////////////////
  1970. // //
  1971. // Change Order Retry Command //
  1972. // //
  1973. /////////////////////////////////////////////////////////////////////
  1974. struct {
  1975. PREPLICA Replica;
  1976. PCHANGE_ORDER_ENTRY ChangeOrderEntry;
  1977. ULONG ChangeOrderSequenceNumber;
  1978. PCXTION Cxtion;
  1979. } UnionCoRetry;
  1980. #define CoRetryReplica(Cmd) (Cmd->Parameters.UnionCoRetry.Replica)
  1981. #define CoRetryCxtion(Cmd) (Cmd->Parameters.UnionCoRetry.Cxtion)
  1982. #define CoRetryChangeOrderEntry(Cmd) (Cmd->Parameters.UnionCoRetry.ChangeOrderEntry)
  1983. #define CoRetrySequenceNumber(Cmd) (Cmd->Parameters.UnionCoRetry.ChangeOrderSequenceNumber)
  1984. /////////////////////////////////////////////////////////////////////
  1985. // //
  1986. // Delayed Command //
  1987. // //
  1988. /////////////////////////////////////////////////////////////////////
  1989. struct {
  1990. PVOID Cs;
  1991. PVOID Cmd;
  1992. PVOID Queue;
  1993. ULONGLONG Timeout;
  1994. } UnionDs;
  1995. /////////////////////////////////////////////////////////////////////
  1996. // //
  1997. // Thread //
  1998. // //
  1999. /////////////////////////////////////////////////////////////////////
  2000. struct {
  2001. PVOID FrsThread;
  2002. } UnionTh;
  2003. /////////////////////////////////////////////////////////////////////
  2004. // //
  2005. // Snd/Rcv //
  2006. // //
  2007. /////////////////////////////////////////////////////////////////////
  2008. struct {
  2009. PVOID CommPkt;
  2010. PVOID To;
  2011. PVOID Replica;
  2012. PVOID Cxtion;
  2013. BOOL JoinGuidValid;
  2014. GUID JoinGuid;
  2015. BOOL SetTimeout;
  2016. PVOID PrincName;
  2017. ULONG AuthLevel;
  2018. PVOID Cs;
  2019. PVOID Cmd;
  2020. ULONGLONG TimeoutSetTime;
  2021. ULONGLONG LastJoinTime;
  2022. } UnionSndRcv;
  2023. /////////////////////////////////////////////////////////////////////
  2024. // //
  2025. // Journal Subsystem Parameters //
  2026. // //
  2027. /////////////////////////////////////////////////////////////////////
  2028. struct {
  2029. //
  2030. // The Context used by journal commands are the Config Table
  2031. // record and the Volume Monitor Entry. Both of these structs
  2032. // are pointed to from the Replica Struct.
  2033. //
  2034. // The ConfigTableRecord has the info about the replica set.
  2035. // e.g. replica number, root path, volume ID, etc.
  2036. //
  2037. // After an initialize call the Journal subsystem creates a
  2038. // volume monitor entry and stores a pointer to it in Replica->pVme.
  2039. // There is a single VME for all the replica sets on a volume.
  2040. // The VME has a ref count tracking the number of active replica sets.
  2041. // The VME is used to manage journal processing on the volume.
  2042. //
  2043. PREPLICA Replica;
  2044. PVOLUME_MONITOR_ENTRY pVme; // pause only uses a VME
  2045. ULONGLONG DFileID;
  2046. } JournalRequest;
  2047. #define JrReplica(Cmd) ((Cmd)->Parameters.JournalRequest.Replica)
  2048. #define JrpVme(Cmd) ((Cmd)->Parameters.JournalRequest.pVme)
  2049. #define JrDFileID(Cmd) ((Cmd)->Parameters.JournalRequest.DFileID)
  2050. /////////////////////////////////////////////////////////////////////
  2051. // //
  2052. // Outbound Log Subsystem Parameters //
  2053. // //
  2054. /////////////////////////////////////////////////////////////////////
  2055. struct {
  2056. //
  2057. // The Context used by outbound log commands is the Replica struct
  2058. // and partner information.
  2059. //
  2060. PREPLICA Replica;
  2061. PCXTION PartnerCxtion;
  2062. struct _CHANGE_ORDER_ENTRY_ *ChangeOrder;
  2063. ULONG SequenceNumber;
  2064. HANDLE CompletionEvent;
  2065. } OutLogRequest;
  2066. /////////////////////////////////////////////////////////////////////
  2067. // //
  2068. // Databse Subsystem Parameters //
  2069. // //
  2070. /////////////////////////////////////////////////////////////////////
  2071. DB_SERVICE_REQUEST DbsRequest;
  2072. /////////////////////////////////////////////////////////////////////
  2073. // //
  2074. // ReplicaState Subsystem Parameters //
  2075. // //
  2076. /////////////////////////////////////////////////////////////////////
  2077. struct {
  2078. //
  2079. // The ReplicaState subsystem manages the data base state for
  2080. // a replica set and provides the means for resyncing that state
  2081. // with the Replica Tree. There are several when a resync
  2082. // is required:
  2083. // 1. Initial creation of replica set state, perhaps with
  2084. // existing data on disk.
  2085. // 2. We lost journal data so we have to do state verification.
  2086. // 3. We lost the database and need to reconstruct.
  2087. // 4. Replica set was restored from a backup tape so the
  2088. // the file ID info and FS USN data needs to be reconstructed.
  2089. //
  2090. USN PickupUsn;
  2091. PREPLICA Replica;
  2092. } ReplicaStateRequest;
  2093. /////////////////////////////////////////////////////////////////////
  2094. // //
  2095. // Staging File Generator Command Server //
  2096. // //
  2097. /////////////////////////////////////////////////////////////////////
  2098. struct {
  2099. //
  2100. // The staging file subsystem generates staging files. This
  2101. // structure is used to pass in parameters to the stageCs
  2102. DWORD StagingSpaceRequestedInKB;
  2103. } StageCsRequest;
  2104. #define StSpaceRequested(Cmd) ((Cmd)->Parameters.StageCsRequest.StagingSpaceRequestedInKB)
  2105. } Parameters;
  2106. };
  2107. #define RsOffsetSkip (0)
  2108. #define RsOffset(_var_) OFFSET(COMMAND_PACKET, Parameters.UnionRs._var_)
  2109. #define RsCompletionEvent(Cmd) (Cmd->Parameters.UnionRs.CompletionEvent)
  2110. #define RsReplicaName(Cmd) ((PGNAME)Cmd->Parameters.UnionRs.ReplicaName)
  2111. #define RsFrom(Cmd) ((PGNAME)Cmd->Parameters.UnionRs.From)
  2112. #define RsTo(Cmd) ((PGNAME)Cmd->Parameters.UnionRs.To)
  2113. #define RsCxtion(Cmd) ((PGNAME)Cmd->Parameters.UnionRs.Cxtion)
  2114. #define RsReplica(Cmd) ((PREPLICA)Cmd->Parameters.UnionRs.Replica)
  2115. #define RsNewReplica(Cmd) ((PREPLICA)Cmd->Parameters.UnionRs.NewReplica)
  2116. #define RsVVector(Cmd) ((PGEN_TABLE)Cmd->Parameters.UnionRs.VVector)
  2117. #define RsReplicaVv(Cmd) ((PGEN_TABLE)Cmd->Parameters.UnionRs.ReplicaVv)
  2118. #define RsCompressionTable(Cmd) (Cmd->Parameters.UnionRs.CompressionTable)
  2119. #define RsJoinGuid(Cmd) ((GUID *)Cmd->Parameters.UnionRs.JoinGuid)
  2120. #define RsJoinTime(Cmd) ((ULONGLONG *)Cmd->Parameters.UnionRs.JoinTime)
  2121. #define RsCommPktRcvTime(Cmd) ((ULONGLONG *)Cmd->Parameters.UnionRs.CommPktRcvTime)
  2122. #define RsLastJoinTime(Cmd) (Cmd->Parameters.UnionRs.LastJoinTime)
  2123. #define RsTimeout(Cmd) ((ULONG)Cmd->Parameters.UnionRs.Timeout)
  2124. #define RsReplicaVersionGuid(Cmd) ((GUID *)Cmd->Parameters.UnionRs.ReplicaVersionGuid)
  2125. #define RsCOTx(Cmd) (Cmd->Parameters.UnionRs.COTx)
  2126. #define RsCommPkts(Cmd) (Cmd->Parameters.UnionRs.CommPkts)
  2127. #define RsMd5Digest(Cmd) (Cmd->Parameters.UnionRs.Md5Digest)
  2128. //
  2129. // Delayed Command Service
  2130. //
  2131. #define DsCs(Cmd) ((PCOMMAND_SERVER)Cmd->Parameters.UnionDs.Cs)
  2132. #define DsCmd(Cmd) ((PCOMMAND_PACKET)Cmd->Parameters.UnionDs.Cmd)
  2133. #define DsQueue(Cmd) ((PFRS_QUEUE)Cmd->Parameters.UnionDs.Queue)
  2134. #define DsTimeout(Cmd) ((ULONGLONG)Cmd->Parameters.UnionDs.Timeout)
  2135. //
  2136. // Thread Subsystem
  2137. //
  2138. #define ThThread(Cmd) ((PFRS_THREAD)Cmd->Parameters.UnionTh.FrsThread)
  2139. //
  2140. // Send/Receive
  2141. //
  2142. #define SRCommPkt(Cmd) ((PCOMM_PACKET)Cmd->Parameters.UnionSndRcv.CommPkt)
  2143. #define SRTo(Cmd) ((PGNAME)Cmd->Parameters.UnionSndRcv.To)
  2144. #define SRCxtion(Cmd) ((PCXTION)Cmd->Parameters.UnionSndRcv.Cxtion)
  2145. #define SRReplica(Cmd) ((PREPLICA)Cmd->Parameters.UnionSndRcv.Replica)
  2146. #define SRSetTimeout(Cmd) (Cmd->Parameters.UnionSndRcv.SetTimeout)
  2147. #define SRJoinGuidValid(Cmd)(Cmd->Parameters.UnionSndRcv.JoinGuidValid)
  2148. #define SRJoinGuid(Cmd) (Cmd->Parameters.UnionSndRcv.JoinGuid)
  2149. #define SRPrincName(Cmd) ((PWCHAR)Cmd->Parameters.UnionSndRcv.PrincName)
  2150. #define SRAuthLevel(Cmd) ((ULONG)Cmd->Parameters.UnionSndRcv.AuthLevel)
  2151. #define SRCmd(Cmd) ((PCOMMAND_PACKET)Cmd->Parameters.UnionSndRcv.Cmd)
  2152. #define SRCs(Cmd) ((PCOMMAND_SERVER)Cmd->Parameters.UnionSndRcv.Cs)
  2153. #define SRTimeoutSetTime(Cmd) (Cmd->Parameters.UnionSndRcv.TimeoutSetTime)
  2154. #define SRLastJoinTime(Cmd) (Cmd->Parameters.UnionSndRcv.TimeoutSetTime)
  2155. //
  2156. // Test
  2157. //
  2158. #define TestIndex(Cmd) ((ULONG)Cmd->Parameters.UnionTest.Index)
  2159. //
  2160. // block of file data for copy
  2161. //
  2162. #define RsFileOffset(Cmd) (Cmd->Parameters.UnionRs.FileOffset)
  2163. #define RsFileSize(Cmd) (Cmd->Parameters.UnionRs.FileSize)
  2164. #define RsBlockSize(Cmd) ((LONGLONG)Cmd->Parameters.UnionRs.BlockSize)
  2165. #define RsBlock(Cmd) ((PUCHAR)Cmd->Parameters.UnionRs.Block)
  2166. //
  2167. // Change Order
  2168. //
  2169. #define RsCoe(Cmd) ((PCHANGE_ORDER_ENTRY) \
  2170. Cmd->Parameters.UnionRs.ChangeOrderEntry)
  2171. #define RsCoc(Cmd) ((PCHANGE_ORDER_COMMAND)&RsCoe(Cmd)->Cmd)
  2172. #define RsPartnerCoc(Cmd) ((PCHANGE_ORDER_COMMAND) \
  2173. Cmd->Parameters.UnionRs.PartnerChangeOrderCommand)
  2174. #define RsPartnerCocExt(Cmd) ((PCHANGE_ORDER_RECORD_EXTENSION) \
  2175. Cmd->Parameters.UnionRs.PartnerChangeOrderCommandExt)
  2176. #define RsGVsn(Cmd) ((PGVSN)Cmd->Parameters.UnionRs.GVsn)
  2177. #define RsCoGuid(Cmd) ((GUID *)Cmd->Parameters.UnionRs.ChangeOrderGuid)
  2178. #define RsCoSn(Cmd) ((ULONG) \
  2179. Cmd->Parameters.UnionRs.ChangeOrderSequenceNumber)
  2180. //
  2181. // Authentication info
  2182. //
  2183. #define RsAuthClient(Cmd) ((PWCHAR)Cmd->Parameters.UnionRs.AuthClient)
  2184. #define RsAuthName(Cmd) ((PWCHAR)Cmd->Parameters.UnionRs.AuthName)
  2185. #define RsAuthLevel(Cmd) (Cmd->Parameters.UnionRs.AuthLevel)
  2186. #define RsAuthN(Cmd) (Cmd->Parameters.UnionRs.AuthN)
  2187. #define RsAuthZ(Cmd) (Cmd->Parameters.UnionRs.AuthZ)
  2188. #define RsAuthSid(Cmd) ((PWCHAR)Cmd->Parameters.UnionRs.AuthSid)
  2189. //
  2190. // Seeding cxtion
  2191. //
  2192. #define RsNewCxtion(Cmd) ((PCXTION)Cmd->Parameters.UnionRs.NewCxtion)
  2193. /******************************************************************************
  2194. *******************************************************************************
  2195. ** **
  2196. ** **
  2197. ** G E N E R I C H A S H T A B L E **
  2198. ** **
  2199. ** **
  2200. *******************************************************************************
  2201. ******************************************************************************/
  2202. //
  2203. // A generic hash table is an array of GENERIC_HASH_ROW_ENTRY structs. Each
  2204. // row entry contains an FRS_LIST struct that has a critical section, a list
  2205. // head and a count. Each entry in the table has a GENERIC_HASH_ENTRY_HEADER
  2206. // at the front of it with a list entry, a ULONG hash value and a reference
  2207. // count. Access to a row of the hash table is controlled by the critical
  2208. // section in the FRS_LIST struct. See genhash.h for more details.
  2209. //
  2210. typedef struct _GENERIC_HASH_TABLE_ {
  2211. FRS_NODE_HEADER Header;
  2212. CHAR Name[16];
  2213. ULONG NumberRows;
  2214. PGENERIC_HASH_FREE_ROUTINE GhtFree;
  2215. PGENERIC_HASH_COMPARE_ROUTINE GhtCompare;
  2216. PGENERIC_HASH_CALC_ROUTINE GhtHashCalc;
  2217. PGENERIC_HASH_PRINT_ROUTINE GhtPrint;
  2218. ULONG KeyOffset;
  2219. ULONG KeyLength;
  2220. BOOL RowLockEnabled;
  2221. BOOL RefCountEnabled;
  2222. HANDLE HeapHandle;
  2223. BOOL UseOffsets;
  2224. ULONG OffsetBase;
  2225. ULONG LockTimeout;
  2226. PGENERIC_HASH_ROW_ENTRY HashRowBase;
  2227. } GENERIC_HASH_TABLE, *PGENERIC_HASH_TABLE;
  2228. /******************************************************************************
  2229. *******************************************************************************
  2230. ** **
  2231. ** **
  2232. ** C H A N G E O R D E R E N T R Y **
  2233. ** **
  2234. ** **
  2235. *******************************************************************************
  2236. ******************************************************************************/
  2237. //
  2238. // The following defines a file or directory change order entry built by the
  2239. // Journal subsystem. These reside in a generic hash table associated with
  2240. // each replica called the ChangeOrderTable. A ptr to the ChangeOrderTable
  2241. // is kept in the REPLICA struct for that replica. The data in an entry
  2242. // comes from the NTFS USN Journal. The FileID is used as the hash table
  2243. // index. In addition the entries are linked on a time ordered list so the
  2244. // Update process can handle them in sequence. An entry in the Change Order
  2245. // Process List is not processed until ChangeOrderAgingDelay seconds has
  2246. // elapsed. This allows time for the NTFS tunnel cache to propagate the
  2247. // tunnelled state into the target file (in particular the object ID). In
  2248. // addition it allows some time to accumulate other file changes into the
  2249. // change order to provide some batching of updates. Each time an existing
  2250. // change order is updated its timestamp is updated to the time of the latest
  2251. // change and the entry moves to the end of the list. To avoid the problem
  2252. // of an entry remaining on the list for an excessive amount of time the time
  2253. // of the initial entry creation is kept. If this time is older than the
  2254. // CHANGE_ORDER_RESIDENCY_DELAY then the entry keeps its place in the list.
  2255. //
  2256. // The Change Order Command is what is actually transmitted to our partners
  2257. // and stored in the database while the operation is pending. Generally the
  2258. // data elements declared in the change order entry are relevant to the local
  2259. // system only while the data elements in the change order command are
  2260. // invarient across replica set members. The Change Order Command is defined
  2261. // in schema.h.
  2262. //
  2263. // Synchronize access to a change order entry using the change order lock table
  2264. // and the macros ChgOrdAcquireLock() and ChgOrdReleaseLock().
  2265. //
  2266. typedef struct _CHANGE_ORDER_ENTRY_ {
  2267. GENERIC_HASH_ENTRY_HEADER HashEntryHeader; // Change Order hash Table support
  2268. UNICODE_STRING UFileName; // Used in renames to make file name bigger
  2269. ULONG EntryFlags; // misc state flags. See below.
  2270. ULONG CoMorphGenCount; // for debugging.
  2271. //
  2272. // Change order process list management.
  2273. //
  2274. LIST_ENTRY ProcessList; // Link on the change order process list.
  2275. ULONG TimeToRun; // Time to process the change order.
  2276. ULONG EntryCreateTime; // Tick Count at entry create time.
  2277. SINGLE_LIST_ENTRY DupCoList; // Duplicate change order list.
  2278. //
  2279. //
  2280. ULONG DirNestingLevel; // Number levels file is down in tree.
  2281. ULONGLONG FileReferenceNumber; // File's FID
  2282. ULONGLONG ParentFileReferenceNumber; // File's parent FID
  2283. PREPLICA OriginalReplica; // ptr to original replica
  2284. PREPLICA NewReplica; // ptr to new replica
  2285. ULONGLONG OriginalParentFid; // For rename processing
  2286. ULONGLONG NewParentFid; // For rename processing
  2287. ULONGLONG NameConflictHashValue; // Key value for NameConflict table cleanup.
  2288. ULONG StreamLastMergeSeqNum; // Stream seq num of last Usn record merged with this CO.
  2289. PREPLICA_THREAD_CTX RtCtx; // For DB access during CO processing.
  2290. GUID *pParentGuid; // ptr to the File's parent Guid in CoCmd.
  2291. GUID FileObjectId; // Object ID read from the file for
  2292. // local change orders. Picked up for tunnelling.
  2293. //
  2294. // The joinguid is a cxtion's session id and, in this case,
  2295. // is used to retry change orders that were accepted by
  2296. // the change order accept thread for a cxtion that has since
  2297. // unjoined from its partner. The change orders for previous
  2298. // sessions are retried because they are out-of-order wrt the
  2299. // change orders for the current session id. In other words,
  2300. // order is maintained per session by coordinating the partners
  2301. // at join time.
  2302. GUID JoinGuid; // Cxtion's session id
  2303. // undefined if local co
  2304. //
  2305. // Remote and control change orders are associated with a cxtion.
  2306. // If this field is non-null, then the field
  2307. // ChangeOrderCount has been incremente for this change
  2308. // order. The count should be decremented when the
  2309. // change order is freed in ChgOrdIssueCleanup().
  2310. //
  2311. PCXTION Cxtion; // NULL if local co
  2312. //
  2313. // Issue cleanup flags -- As a change order is processed it acquires
  2314. // various resources that must be released when it retires or goes thru
  2315. // retry. The ISCU flag bits below are used to set these bits. Note:
  2316. // Not all bits may be set here. Some may get set just before the CO goes
  2317. // thru cleanup.
  2318. //
  2319. ULONG IssueCleanup;
  2320. //
  2321. // Save full path name when the install code generates it for tracking.
  2322. //
  2323. PWCHAR FullPathName;
  2324. //
  2325. // Needed to dampen basic info changes (e.g., resetting the archive bit)
  2326. // Copied from the idtable entry when the change order is created and
  2327. // used to update the change order when the change order is retired.
  2328. //
  2329. ULONG FileAttributes;
  2330. LARGE_INTEGER FileCreateTime;
  2331. LARGE_INTEGER FileWriteTime;
  2332. //
  2333. // Store the current offset of the staging file that we are waiting for.
  2334. // Used to discard responses that do not match the current offset we are
  2335. // expecting.
  2336. //
  2337. //LARGE_INTEGER FileOffset;
  2338. //
  2339. // Change order command parameters.
  2340. // (must be last since it ends with FileName)
  2341. //
  2342. CHANGE_ORDER_COMMAND Cmd;
  2343. } CHANGE_ORDER_ENTRY, *PCHANGE_ORDER_ENTRY;
  2344. //
  2345. // This structure is used by the JrnlDoesChangeOrderHaveChildren to pass data to the
  2346. // JrnlDoesChangeOrderHaveChildrenWorker function.
  2347. //
  2348. typedef struct _VALID_CHILD_CHECK_DATA {
  2349. PTHREAD_CTX ThreadCtx;
  2350. PTABLE_CTX TmpIDTableCtx;
  2351. ULONGLONG FileReferenceNumber;
  2352. } VALID_CHILD_CHECK_DATA, *PVALID_CHILD_CHECK_DATA;
  2353. //
  2354. // EntryFlags defs.
  2355. //
  2356. #define COE_FLAG_VOL_COLIST_BLOCKED 0x00000001
  2357. #define COE_FLAG_STAGE_ABORTED 0x00000002
  2358. #define COE_FLAG_STAGE_DELETED 0x00000004
  2359. #define COE_FLAG_NEED_RENAME 0x00000008
  2360. #define COE_FLAG_IN_AGING_CACHE 0x00000010
  2361. #define COE_FLAG_RECOVERY_CO 0x00000020 // CO is part of cxtion recovery/restart
  2362. #define COE_FLAG_NO_INBOUND 0x00000040 // The inbound partner cxtion is gone.
  2363. #define COE_FLAG_JUST_TOMBSTONE 0x00000080 // Creating file delete tombstone in IDTable
  2364. #define COE_FLAG_REJECT_AT_RECONCILE 0x00000100 // Always reject during reconcile
  2365. #define COE_FLAG_MOVEOUT_ENUM_DONE 0x00000200 // Set when the moveout enum is done for this CO
  2366. #define COE_FLAG_DELETE_GEN_CO 0x00000400 // Set for delete COs created by moveout ENUMS.
  2367. #define COE_FLAG_REANIMATION 0x00000800 // This CO is a reanimation request.
  2368. #define COE_FLAG_PARENT_REANIMATION 0x00001000 // This CO is for a reanimated parent.
  2369. #define COE_FLAG_PARENT_RISE_REQ 0x00002000 // This CO has previously requested
  2370. // reanimation of its parent.
  2371. #define COE_FLAG_MORPH_GEN_FOLLOWER 0x00004000 // This is the MorphGenFollower of a Morph Gen pair.
  2372. #define COE_FLAG_MG_FOLLOWER_MADE 0x00008000 // Set in the MorphGenLeader when the Follower
  2373. // CO is fabricated.
  2374. #define COE_FLAG_NEED_DELETE 0x00010000 // This CO must retry target delete.
  2375. #define COE_FLAG_PREINSTALL_CRE 0x00020000 // A preinstall file was created for this CO.
  2376. #define COE_FLAG_PRE_EXIST_MD5_MATCH 0x00040000 // The MD5 check with a pre-existing file is a match.
  2377. #define COE_FLAG_OID_FROM_FILE 0x00080000 // The incoming file has an OID (stored in Coe->FileObjectId)
  2378. #define COE_FLAG_IDT_NEW_PARENT_DEL_DEF 0x01000000 // IDTable shows New parent dir is delete deferred.
  2379. #define COE_FLAG_TRY_OVRIDE_INSTALL 0x02000000 // We hit a sharing violation on destination. Try rename to unblock.
  2380. #define COE_FLAG_IDT_ORIG_PARENT_DEL 0x04000000 // IDTable shows orig parent dir is deleted.
  2381. #define COE_FLAG_IDT_ORIG_PARENT_ABS 0x08000000 // IDTable shows orig parent dir record is absent.
  2382. #define COE_FLAG_IDT_NEW_PARENT_DEL 0x10000000 // IDTable shows New parent dir is deleted.
  2383. #define COE_FLAG_IDT_NEW_PARENT_ABS 0x20000000 // IDTable shows New parent dir record is absent.
  2384. #define COE_FLAG_IDT_TARGET_DEL 0x40000000 // IDTable shows Target file/dir of CO is deleted.
  2385. #define COE_FLAG_IDT_TARGET_ABS 0x80000000 // IDTable shows Target file/dir of CO is absent.
  2386. #define COE_FLAG_GROUP_REANIMATE (COE_FLAG_REANIMATION | \
  2387. COE_FLAG_PARENT_REANIMATION | \
  2388. COE_FLAG_PARENT_RISE_REQ)
  2389. #define COE_FLAG_GROUP_RAISE_DEAD_PARENT (COE_FLAG_REANIMATION | \
  2390. COE_FLAG_PARENT_REANIMATION)
  2391. #define RecoveryCo(_COE_) COE_FLAG_ON(_COE_, COE_FLAG_RECOVERY_CO)
  2392. #define COE_FLAG_ON(_COE_, _F_) (BooleanFlagOn((_COE_)->EntryFlags, (_F_)))
  2393. #define SET_COE_FLAG(_COE_, _F_) SetFlag((_COE_)->EntryFlags, (_F_))
  2394. #define CLEAR_COE_FLAG(_COE_, _F_) ClearFlag((_COE_)->EntryFlags, (_F_))
  2395. //
  2396. // The change order cleanup flags are used to control the state that needs
  2397. // to be updated when a change order fails to issue, is rejected or retires.
  2398. //
  2399. #define ISCU_DEL_PREINSTALL 0x00000001
  2400. #define ISCU_DEL_IDT_ENTRY 0x00000002
  2401. #define ISCU_UPDATE_IDT_ENTRY 0x00000004
  2402. #define ISCU_DEL_INLOG 0x00000008 // conditioned on ref count zero
  2403. #define ISCU_AIBCO 0x00000010
  2404. #define ISCU_ACTIVE_CHILD 0x00000020
  2405. #define ISCU_UPDATE_IDT_VVFLAGS 0x00000040
  2406. #define ISCU_CHECK_ISSUE_BLOCK 0x00000080
  2407. #define ISCU_DEL_RTCTX 0x00000100 // conditioned on ref count zero
  2408. #define ISCU_ACTIVATE_VV 0x00000200
  2409. #define ISCU_UPDATEVV_DB 0x00000400
  2410. #define ISCU_ACTIVATE_VV_DISCARD 0x00000800
  2411. #define ISCU_ACK_INBOUND 0x00001000
  2412. #define ISCU_INS_OUTLOG 0x00002000
  2413. #define ISCU_UPDATE_INLOG 0x00004000
  2414. #define ISCU_DEL_STAGE_FILE 0x00008000
  2415. #define ISCU_DEL_STAGE_FILE_IF 0x00010000
  2416. #define ISCU_FREE_CO 0x00020000 // conditioned on ref count zero
  2417. #define ISCU_DEC_CO_REF 0x00040000
  2418. #define ISCU_CO_ABORT 0x00080000
  2419. #define ISCU_NC_TABLE 0x00100000
  2420. #define ISCU_SPARE1 0x00200000
  2421. #define ISCU_UPDATE_IDT_FLAGS 0x00400000
  2422. #define ISCU_UPDATE_IDT_FILEUSN 0x00800000
  2423. #define ISCU_INS_OUTLOG_NEW_GUID 0x01000000 // modifier on _INS_OUTLOG
  2424. #define ISCU_UPDATE_IDT_VERSION 0x02000000
  2425. #define ISCU_NO_CLEANUP_MERGE 0x80000000
  2426. #define SET_ISSUE_CLEANUP(_Coe_, _Flag_) \
  2427. SetFlag((_Coe_)->IssueCleanup, (_Flag_))
  2428. #define CLEAR_ISSUE_CLEANUP(_Coe_, _Flag_) \
  2429. ClearFlag((_Coe_)->IssueCleanup, (_Flag_))
  2430. #define ZERO_ISSUE_CLEANUP(_Coe_) (_Coe_)->IssueCleanup = 0
  2431. //
  2432. // ISCU_GOIS_CLEANUP clears Issue Clean up flags once we decide to issue CO.
  2433. //
  2434. #define ISCU_GOIS_CLEANUP (ISCU_DEL_PREINSTALL | \
  2435. ISCU_DEL_IDT_ENTRY)
  2436. //
  2437. // HOLDIS_CLEANUP removes state from the CO hold issue conflict tables.
  2438. //
  2439. #define ISCU_HOLDIS_CLEANUP (ISCU_AIBCO | \
  2440. ISCU_ACTIVE_CHILD | \
  2441. ISCU_NC_TABLE | \
  2442. ISCU_CHECK_ISSUE_BLOCK)
  2443. //
  2444. // FREEMEM_CLEANUP decrements the CO reference count and deletes the CO if the
  2445. // count goes to zero.
  2446. //
  2447. #define ISCU_FREEMEM_CLEANUP (ISCU_DEC_CO_REF | \
  2448. ISCU_DEL_RTCTX | \
  2449. ISCU_FREE_CO)
  2450. //
  2451. // ISSUE_CLEANUP does the hold issue conflict cleanup and deletes the CO if the
  2452. // reference count goes to zero.
  2453. //
  2454. #define ISCU_ISSUE_CLEANUP (ISCU_HOLDIS_CLEANUP | \
  2455. ISCU_FREEMEM_CLEANUP)
  2456. #define REPLICA_CHANGE_ORDER_ENTRY_KEY \
  2457. OFFSET(CHANGE_ORDER_ENTRY, FileReferenceNumber)
  2458. #define REPLICA_CHANGE_ORDER_ENTRY_KEY_LENGTH sizeof(ULONGLONG)
  2459. #define REPLICA_CHANGE_ORDER_FILEGUID_KEY \
  2460. OFFSET(CHANGE_ORDER_ENTRY, Cmd.FileGuid)
  2461. #define REPLICA_CHANGE_ORDER_FILEGUID_KEY_LENGTH sizeof(GUID)
  2462. #define REPLICA_CHANGE_ORDER_HASH_TABLE_ROWS 128
  2463. #define ACTIVE_INBOUND_CHANGE_ORDER_HASH_TABLE_ROWS 32
  2464. //
  2465. // Change order aging delay should be a min of 3 sec to allow for tunnel cache
  2466. // data to propagate. Units are in milliseconds.
  2467. //
  2468. #define CHANGE_ORDER_RESIDENCY_DELAY 600
  2469. #define CO_TIME_TO_RUN(_pVme_) (GetTickCount() + ChangeOrderAgingDelay)
  2470. #define CO_TIME_NOW(_pVme_) (GetTickCount())
  2471. #define CO_REPLICA(_coe_) \
  2472. (((_coe_)->NewReplica != NULL) ? (_coe_)->NewReplica \
  2473. : (_coe_)->OriginalReplica)
  2474. #define CHANGE_ORDER_TRACE(_sev, _coe, _text) \
  2475. ChgOrdTraceCoe(_sev, DEBSUB, __LINE__, _coe, _text)
  2476. #define CHANGE_ORDER_TRACEW(_sev, _coe, _text, _wstatus) \
  2477. ChgOrdTraceCoeW(_sev, DEBSUB, __LINE__, _coe, _text, _wstatus)
  2478. #define CHANGE_ORDER_TRACEX(_sev, _coe, _text, _data) \
  2479. ChgOrdTraceCoeX(_sev, DEBSUB, __LINE__, _coe, _text, _data)
  2480. #define CHANGE_ORDER_TRACEF(_sev, _coe, _text, _fstatus) \
  2481. ChgOrdTraceCoeF(_sev, DEBSUB, __LINE__, _coe, _text, _fstatus)
  2482. #define CHANGE_ORDER_TRACEXP(_sev, _coe, _text, _data) \
  2483. ChgOrdTraceCoeX(_sev, DEBSUB, __LINE__, _coe, _text, PtrToUlong(_data))
  2484. #define CHANGE_ORDER_COMMAND_TRACE(_sev, _coc, _text) \
  2485. ChgOrdTraceCoc(_sev, DEBSUB, __LINE__, _coc, _text)
  2486. #define CHANGE_ORDER_COMMAND_TRACEW(_sev, _coc, _text, _wstatus) \
  2487. ChgOrdTraceCocW(_sev, DEBSUB, __LINE__, _coc, _text, _wstatus)
  2488. #define CHANGE_ORDER_TRACE2_OLOG(_sev, _cmd, _text, _Replica, _Cxtion) \
  2489. { \
  2490. CHAR Tstr[256]; \
  2491. _snprintf(Tstr, sizeof(Tstr), "OL%s "FORMAT_CXTION_PATH2, _text, \
  2492. PRINT_CXTION_PATH2(_Replica, _Cxtion)); \
  2493. Tstr[sizeof(Tstr)-1] = '\0'; \
  2494. ChgOrdTraceCoc(_sev, DEBSUB, __LINE__, _cmd, Tstr); \
  2495. }
  2496. #define FRS_TRACK_RECORD(_coe, _text) \
  2497. FrsTrackRecord(2, DEBSUB, __LINE__, _coe, _text)
  2498. #define INCREMENT_CHANGE_ORDER_REF_COUNT(_coe) \
  2499. InterlockedIncrement(&((_coe)->HashEntryHeader.ReferenceCount)); \
  2500. ChgOrdTraceCoeX(3, DEBSUB, __LINE__, _coe, "Co Inc Ref to ", \
  2501. (_coe)->HashEntryHeader.ReferenceCount)
  2502. #define DECREMENT_CHANGE_ORDER_REF_COUNT(_coe) \
  2503. InterlockedDecrement(&((_coe)->HashEntryHeader.ReferenceCount)); \
  2504. ChgOrdTraceCoeX(3, DEBSUB, __LINE__, _coe, "Co Dec Ref to ", \
  2505. (_coe)->HashEntryHeader.ReferenceCount)
  2506. // Note: add coe delete code if we care that refcount goes to zero.
  2507. #define GET_CHANGE_ORDER_REF_COUNT(_coe) \
  2508. ((_coe)->HashEntryHeader.ReferenceCount); \
  2509. ChgOrdTraceCoeX(3, DEBSUB, __LINE__, _coe, "Co Get Ref Cnt", \
  2510. (_coe)->HashEntryHeader.ReferenceCount)
  2511. /******************************************************************************
  2512. *******************************************************************************
  2513. ** **
  2514. ** **
  2515. ** J O U R N A L F I L T E R T A B L E E N T R Y **
  2516. ** **
  2517. ** **
  2518. *******************************************************************************
  2519. ******************************************************************************/
  2520. //
  2521. // The Volume Filter Table Entry holds the file ID of a directory in
  2522. // a replica set. As journal entries are processed the parent file ID of
  2523. // each journal record is used to lookup the filter table entry in the
  2524. // volume filter hash table (for the volume). If it finds a match we
  2525. // know that the journal entry is for a file in a replica set on the
  2526. // volume. The replica number field tells us which replica set it belongs
  2527. // too. Consecutive lookups on the parent file ID yields the relative
  2528. // directory path for the file.
  2529. //
  2530. // The DTransition field is used to manage directory renames. It contains a
  2531. // sequence number and a type field describing the nature of the directory
  2532. // rename operation. See JrnlFilterUpdate() for details.
  2533. //
  2534. typedef struct _FILTER_TABLE_ENTRY_ {
  2535. GENERIC_HASH_ENTRY_HEADER HashEntryHeader;
  2536. PREPLICA Replica;
  2537. ULONG DTransition; // used?? // <31:2> are seq number, <1:0> are Trans Type
  2538. LIST_ENTRY ChildHead; // List head for this entry's children.
  2539. LIST_ENTRY ChildEntry; // Entry link for children.
  2540. ULONGLONG FrsVsn; // used?? // The FrsVsn for latest DIR change.
  2541. UNICODE_STRING UFileName; // Used in renames to make file name bigger
  2542. //
  2543. // The layout of the following MUST match the DIRTable Record layout
  2544. // in schema.h
  2545. //
  2546. ULONGLONG DFileID;
  2547. ULONGLONG DParentFileID;
  2548. ULONG DReplicaNumber;
  2549. WCHAR DFileName[1];
  2550. } FILTER_TABLE_ENTRY, *PFILTER_TABLE_ENTRY;
  2551. #define VOLUME_FILTER_HASH_TABLE_ROWS 256
  2552. #define FILTER_ENTRY_TRANS_STABLE 0
  2553. #define FILTER_ENTRY_TRANS_MOVE 1
  2554. #define FILTER_ENTRY_TRANS_DELETE 2
  2555. #define FILTER_ENTRY_TRANS_MASK 0x3
  2556. #define FILTER_ENTRY_TRANS_SHIFT 2
  2557. #define INCREMENT_FILTER_SEQ_NUMBER(_Entry_) \
  2558. (((_Entry_)->DTransition += (1<<FILTER_ENTRY_TRANS_SHIFT)) >> \
  2559. FILTER_ENTRY_TRANS_SHIFT)
  2560. #define READ_FILTER_SEQ_NUMBER(_Entry_) \
  2561. (((_Entry_)->DTransition) >> FILTER_ENTRY_TRANS_SHIFT)
  2562. #define SET_FILTER_TRANS_TYPE(_Entry_, _TYPE_) \
  2563. (_Entry_)->DTransition = \
  2564. ((_Entry_)->DTransition & ~FILTER_ENTRY_TRANS_MASK) | _TYPE_
  2565. #define READ_FILTER_TRANS_TYPE(_Entry_) \
  2566. (_Entry_)->DTransition &= FILTER_ENTRY_TRANS_MASK
  2567. #define INCREMENT_FILTER_REF_COUNT(_Entry_) \
  2568. InterlockedIncrement(&((_Entry_)->HashEntryHeader.ReferenceCount)); \
  2569. DPRINT2(5, "inc ref: %08x, %d\n", (PtrToUlong(_Entry_)), (_Entry_)->HashEntryHeader.ReferenceCount);
  2570. #define DECREMENT_FILTER_REF_COUNT(_Entry_) \
  2571. InterlockedDecrement(&((_Entry_)->HashEntryHeader.ReferenceCount)); \
  2572. DPRINT2(5, "dec ref: %08x, %d\n", (PtrToUlong(_Entry_)), (_Entry_)->HashEntryHeader.ReferenceCount);
  2573. /******************************************************************************
  2574. *******************************************************************************
  2575. ** **
  2576. ** **
  2577. ** W I L D C A R D F I L T E R E N T R Y **
  2578. ** **
  2579. ** **
  2580. *******************************************************************************
  2581. ******************************************************************************/
  2582. //
  2583. // There are two wildcard filter lists in FRS. One is for files and the other
  2584. // is for directories. These filters are per-replica set and get loaded from
  2585. // the DS when the service starts on the given replica set.
  2586. //
  2587. typedef struct _WILDCARD_FILTER_ENTRY_ {
  2588. FRS_NODE_HEADER Header;
  2589. LIST_ENTRY ListEntry; // MUST FOLLOW HEADER
  2590. ULONG Flags;
  2591. UNICODE_STRING UFileName;
  2592. WCHAR FileName[1];
  2593. } WILDCARD_FILTER_ENTRY, *PWILDCARD_FILTER_ENTRY;
  2594. #define WILDCARD_FILTER_ENTRY_IS_WILD 0x1
  2595. //
  2596. // Global Jet Instance handle
  2597. //
  2598. extern JET_INSTANCE GJetInstance;
  2599. //
  2600. // Note: Would be nice to clean this up.
  2601. // Note: Defs depend on PREPLICA, TABLE_CTX and JET_SESID but shouldn't be here.
  2602. //
  2603. ULONG
  2604. FrsSupMakeFullFileName(
  2605. IN PREPLICA Replica,
  2606. IN PWCHAR RelativeName,
  2607. OUT PWCHAR FullName,
  2608. IN ULONG MaxLength
  2609. );
  2610. BOOL
  2611. FrsCloseWithUsnDampening(
  2612. IN PWCHAR Name,
  2613. IN OUT PHANDLE Handle,
  2614. IN PQHASH_TABLE FrsWriteFilter,
  2615. OUT USN *RetUsn
  2616. );
  2617. //
  2618. // frsalloc.c needs the next two.
  2619. //
  2620. NTSTATUS
  2621. DbsAllocTableCtx(
  2622. IN TABLE_TYPE TableType,
  2623. IN OUT PTABLE_CTX TableCtx
  2624. );
  2625. NTSTATUS
  2626. DbsAllocTableCtxWithRecord(
  2627. IN TABLE_TYPE TableType,
  2628. IN OUT PTABLE_CTX TableCtx,
  2629. IN PVOID DataRecord
  2630. );
  2631. VOID
  2632. DbsFreeTableCtx(
  2633. IN OUT PTABLE_CTX TableCtx,
  2634. IN ULONG NodeType
  2635. );
  2636. //
  2637. // MEMORY MANAGEMENT ROUTINES
  2638. //
  2639. //
  2640. // Allocate and zero a chunk of memory. An exception is raised if memory
  2641. // could not be allocated.
  2642. //
  2643. PVOID
  2644. FrsAlloc(
  2645. IN DWORD NodeSize
  2646. );
  2647. //
  2648. // Reallocate and zero a chunk of memory. An exception is raised if memory
  2649. // could not be allocated.
  2650. //
  2651. PVOID
  2652. FrsRealloc(
  2653. IN PVOID OldNode,
  2654. IN DWORD NodeSize
  2655. );
  2656. //
  2657. // Allocate and initialize a struct of the specified type. The memory is
  2658. // zeroed and the FRS_NODE_HEADER is initialized. The total allocation is
  2659. // the size of the base type PLUS the SizeDelta.
  2660. //
  2661. PVOID
  2662. FrsAllocTypeSize(
  2663. IN NODE_TYPE NodeType,
  2664. IN ULONG SizeDelta
  2665. );
  2666. //
  2667. // Free the memory allocated with FrsAlloc.
  2668. //
  2669. PVOID
  2670. FrsFree(
  2671. IN PVOID Node
  2672. );
  2673. //
  2674. // Free the memory allocated with FrsAllocType.
  2675. //
  2676. // Check the embedded FRS_NODE_HEADER for correctness, Scribble on
  2677. // the memory, and then free it.
  2678. //
  2679. PVOID
  2680. FrsFreeType(
  2681. IN PVOID Node
  2682. );
  2683. VOID
  2684. FrsPrintTypeReplica(
  2685. IN ULONG Severity, OPTIONAL
  2686. IN PVOID Info, OPTIONAL
  2687. IN DWORD Tabs, OPTIONAL
  2688. IN PREPLICA Replica,
  2689. IN PCHAR Debsub, OPTIONAL
  2690. IN ULONG uLineNo OPTIONAL
  2691. );
  2692. VOID
  2693. FrsPrintTypeSchedule(
  2694. IN ULONG Severity, OPTIONAL
  2695. IN PVOID Info, OPTIONAL
  2696. IN DWORD Tabs, OPTIONAL
  2697. IN PSCHEDULE Schedule,
  2698. IN PCHAR Debsub, OPTIONAL
  2699. IN ULONG uLineNo OPTIONAL
  2700. );
  2701. //
  2702. // Print out the contents of a node.
  2703. //
  2704. VOID
  2705. FrsPrintType(
  2706. IN ULONG Severity,
  2707. IN PVOID Node,
  2708. IN PCHAR Debsub,
  2709. IN ULONG uLineNo
  2710. );
  2711. #define FRS_PRINT_TYPE(_Severity, _Node) \
  2712. FrsPrintType(_Severity, _Node, DEBSUB, __LINE__)
  2713. #define FRS_PRINT_TYPE_DEBSUB(_Severity, _DebSub, _Node) \
  2714. FrsPrintType(_Severity, _Node, _DebSub, __LINE__)
  2715. //
  2716. // Take a list of "Typed" entries and free each entry.
  2717. // *** Note *** Each entry must be linked through a LIST_ENTRY struct that
  2718. // is declared immediately after the FRS_NODE_HEADER.
  2719. //
  2720. VOID
  2721. FrsFreeTypeList(
  2722. PLIST_ENTRY Head
  2723. );
  2724. //
  2725. // Duplicate a wide char string into a char string
  2726. //
  2727. PCHAR
  2728. FrsWtoA(
  2729. IN PWCHAR Wstr
  2730. );
  2731. //
  2732. // Duplicate a wide char string into a char string
  2733. //
  2734. PWCHAR
  2735. FrsAtoW(
  2736. IN PCHAR Astr
  2737. );
  2738. //
  2739. // Duplicate a string using our memory management routines
  2740. //
  2741. PWCHAR
  2742. FrsWcsDup(
  2743. IN PWCHAR OldStr
  2744. );
  2745. //
  2746. // Extract the volume name (drive:\) from Path
  2747. //
  2748. PWCHAR
  2749. FrsWcsVolume(
  2750. IN PWCHAR Path
  2751. );
  2752. //
  2753. // Concatenate first and second into a new string using our
  2754. // memory management routines
  2755. //
  2756. PWCHAR
  2757. FrsWcsCat(
  2758. IN PWCHAR First,
  2759. IN PWCHAR Second
  2760. );
  2761. PWCHAR
  2762. FrsWcsCat3(
  2763. IN PWCHAR First,
  2764. IN PWCHAR Second,
  2765. IN PWCHAR Third
  2766. );
  2767. //
  2768. // Char version of FrsWcsCat()
  2769. //
  2770. PCHAR
  2771. FrsCsCat(
  2772. IN PCHAR First,
  2773. IN PCHAR Second
  2774. );
  2775. //
  2776. // Concatenate first and second into a new path string using our
  2777. // memory management routines
  2778. //
  2779. PWCHAR
  2780. FrsWcsPath(
  2781. IN PWCHAR First,
  2782. IN PWCHAR Second
  2783. );
  2784. //
  2785. // Char version of FrsWcsPath
  2786. //
  2787. PCHAR
  2788. FrsCsPath(
  2789. IN PCHAR First,
  2790. IN PCHAR Second
  2791. );
  2792. //
  2793. // Initialize a unicode string with the contents of Wstr if the two are
  2794. // not already the same. If the length of the new string is greater than
  2795. // the buffer space currently allocated in Ustr then allocate a new
  2796. // buffer for Ustr. In some structures the initial Ustr buffer allocation
  2797. // is allocated as part of the initial structure allocation. The address
  2798. // of this internal buffer is passed so it can be compared with the address
  2799. // in Ustr->Buffer. If they match then no free memory call is made on
  2800. // the Ustr->Buffer address. WstrLength is in bytes and should not include the
  2801. // trailing UNICODE_NULL. Space is allocated for the NULL in the new buffer
  2802. // and a UNICODE_NULL is placed at the end of the string so it can be printed.
  2803. //
  2804. VOID
  2805. FrsAllocUnicodeString(
  2806. PUNICODE_STRING Ustr,
  2807. PWCHAR InternalBuffer,
  2808. PWCHAR Wstr,
  2809. USHORT WstrLength
  2810. );
  2811. //
  2812. // Remove the Trim char from the trailing end of the string.
  2813. // return a ptr to the first non Trim-Char in the string.
  2814. //
  2815. PWCHAR
  2816. FrsWcsTrim(
  2817. PWCHAR Wstr,
  2818. WCHAR Trim
  2819. );
  2820. /*
  2821. VOID
  2822. FrsCopyUnicodeStringFromRawString(
  2823. PUNICODE_STRING _UStr,
  2824. ULONG _Maxlen,
  2825. PWSTR _WStr,
  2826. ULONG _Len
  2827. )
  2828. Init the unicode string struct by coping the data from _WStr.
  2829. _UStr - ptr to unicode string struct
  2830. _Maxlen is the size of the unicode string buffer
  2831. _WStr is ptr to non-terminated unicode string.
  2832. _Len is the length of the unicode string.
  2833. Terminate the copied string with a Unicode null if room in the buffer.
  2834. The terminating null is not included in the length.
  2835. */
  2836. #define FrsCopyUnicodeStringFromRawString(_UStr, _Maxlen, _WStr, _Len) \
  2837. FRS_ASSERT((_Maxlen) >= (_Len)); \
  2838. FRS_ASSERT((_UStr) != NULL); \
  2839. FRS_ASSERT((_WStr) != NULL); \
  2840. \
  2841. (_UStr)->Length = (USHORT)(_Len); \
  2842. CopyMemory((_UStr)->Buffer, _WStr, _Len); \
  2843. (_UStr)->MaximumLength = (USHORT)(_Maxlen); \
  2844. if ((_Maxlen) > (_Len)) { \
  2845. (_UStr)->Buffer[(_Len)/2] = UNICODE_NULL; \
  2846. }
  2847. /*
  2848. VOID
  2849. FrsSetUnicodeStringFromRawString(
  2850. PUNICODE_STRING _UStr,
  2851. ULONG _Maxlen,
  2852. PWSTR _WStr,
  2853. ULONG _Len
  2854. )
  2855. Init the unicode string struct by setting the address of _WStr into _UStr.
  2856. No string copy is done.
  2857. _UStr - ptr to unicode string struct
  2858. _Maxlen is the size of the unicode string buffer
  2859. _WStr is ptr to non-terminated unicode string.
  2860. _Len is the length of the unicode string.
  2861. Terminate the string with a Unicode null if room in the buffer.
  2862. The terminating null is not included in the length.
  2863. */
  2864. #define FrsSetUnicodeStringFromRawString(_UStr, _Maxlen, _WStr, _Len) \
  2865. FRS_ASSERT((_Maxlen) >= (_Len)); \
  2866. FRS_ASSERT((_UStr) != NULL); \
  2867. FRS_ASSERT((_WStr) != NULL); \
  2868. \
  2869. (_UStr)->Length = (USHORT)(_Len); \
  2870. (_UStr)->Buffer = (_WStr); \
  2871. (_UStr)->MaximumLength = (USHORT)(_Maxlen); \
  2872. if ((_Maxlen) > (_Len)) { \
  2873. (_UStr)->Buffer[(_Len)/2] = UNICODE_NULL; \
  2874. }
  2875. //
  2876. // Replica Startup / Shutdown Trace
  2877. //
  2878. #define REPLICA_STATE_TRACE(_sev, _cmd, _replica, _status, _text) \
  2879. ReplicaStateTrace(_sev, DEBSUB, __LINE__, (PCOMMAND_PACKET)(_cmd), _replica, _status, _text)
  2880. //
  2881. // Cxtion state Trace
  2882. //
  2883. #define CXTION_STATE_TRACE(_sev, _cxtion, _replica, _status, _text) \
  2884. CxtionStateTrace(_sev, DEBSUB, __LINE__, (PCXTION)(_cxtion), _replica, _status, _text)
  2885. //
  2886. // Trace command packet
  2887. //
  2888. #define COMMAND_TRACE(_sev, _cmd, _text) \
  2889. CmdPktTrace(_sev, DEBSUB, __LINE__, (_cmd), _text)
  2890. //
  2891. // Trace command with snd-comm packet
  2892. //
  2893. #define COMMAND_SND_COMM_TRACE(_sev, _cmd, _wstatus, _text) \
  2894. SendCmdTrace(_sev, DEBSUB, __LINE__, _cmd, _wstatus, _text)
  2895. //
  2896. // Trace command with rcv-comm packet
  2897. //
  2898. #define COMMAND_RCV_TRACE(_sev, _cmd, _cxtion, _wstatus, _text) \
  2899. ReceiveCmdTrace(_sev, DEBSUB, __LINE__, _cmd, _cxtion, _wstatus, _text)
  2900. //
  2901. // Trace command with comm packet
  2902. //
  2903. #define COMMAND_RCV_AUTH_TRACE(_sev, _comm, _wstatus, _authl, _authn, _client, _princname, _text) \
  2904. DPRINT8(_sev, ":SR: Comm %08x, Len %d, WS %d, Lev %d, AuthN %d, From %ws, To %ws [%s]\n", \
  2905. (PtrToUlong(_comm)), \
  2906. (_comm) ? _comm->PktLen : 0, \
  2907. _wstatus, \
  2908. _authl, \
  2909. _authn, \
  2910. _client, \
  2911. _princname, \
  2912. _text)
  2913. //
  2914. // Various trace functions. (frsalloc.c)
  2915. //
  2916. VOID
  2917. ChgOrdTraceCoe(
  2918. IN ULONG Severity,
  2919. IN PCHAR Debsub,
  2920. IN ULONG uLineNo,
  2921. IN PCHANGE_ORDER_ENTRY Coe,
  2922. IN PCHAR Text
  2923. );
  2924. VOID
  2925. ChgOrdTraceCoeW(
  2926. IN ULONG Severity,
  2927. IN PCHAR Debsub,
  2928. IN ULONG uLineNo,
  2929. IN PCHANGE_ORDER_ENTRY Coe,
  2930. IN PCHAR Text,
  2931. IN ULONG WStatus
  2932. );
  2933. VOID
  2934. ChgOrdTraceCoeF(
  2935. IN ULONG Severity,
  2936. IN PCHAR Debsub,
  2937. IN ULONG uLineNo,
  2938. IN PCHANGE_ORDER_ENTRY Coe,
  2939. IN PCHAR Text,
  2940. IN ULONG FStatus
  2941. );
  2942. VOID
  2943. ChgOrdTraceCoeX(
  2944. IN ULONG Severity,
  2945. IN PCHAR Debsub,
  2946. IN ULONG uLineNo,
  2947. IN PCHANGE_ORDER_ENTRY Coe,
  2948. IN PCHAR Text,
  2949. IN ULONG Data
  2950. );
  2951. VOID
  2952. ChgOrdTraceCoc(
  2953. IN ULONG Severity,
  2954. IN PCHAR Debsub,
  2955. IN ULONG uLineNo,
  2956. IN PCHANGE_ORDER_COMMAND Coc,
  2957. IN PCHAR Text
  2958. );
  2959. VOID
  2960. ChgOrdTraceCocW(
  2961. IN ULONG Severity,
  2962. IN PCHAR Debsub,
  2963. IN ULONG uLineNo,
  2964. IN PCHANGE_ORDER_COMMAND Coc,
  2965. IN PCHAR Text,
  2966. IN ULONG WStatus
  2967. );
  2968. VOID
  2969. FrsTrackRecord(
  2970. IN ULONG Severity,
  2971. IN PCHAR Debsub,
  2972. IN ULONG uLineNo,
  2973. IN PCHANGE_ORDER_ENTRY Coe,
  2974. IN PCHAR Text
  2975. );
  2976. VOID
  2977. ReplicaStateTrace(
  2978. IN ULONG Severity,
  2979. IN PCHAR Debsub,
  2980. IN ULONG uLineNo,
  2981. IN PCOMMAND_PACKET Cmd,
  2982. IN PREPLICA Replica,
  2983. IN ULONG Status,
  2984. IN PCHAR Text
  2985. );
  2986. VOID
  2987. ReplicaStateTrace2(
  2988. IN ULONG Severity,
  2989. IN PCHAR Debsub,
  2990. IN ULONG uLineNo,
  2991. IN PREPLICA Replica,
  2992. IN PCHAR Text
  2993. );
  2994. VOID
  2995. CxtionStateTrace(
  2996. IN ULONG Severity,
  2997. IN PCHAR Debsub,
  2998. IN ULONG uLineNo,
  2999. IN PCXTION Cxtion,
  3000. IN PREPLICA Replica,
  3001. IN ULONG Status,
  3002. IN PCHAR Text
  3003. );
  3004. VOID
  3005. CmdPktTrace(
  3006. IN ULONG Severity,
  3007. IN PCHAR Debsub,
  3008. IN ULONG uLineNo,
  3009. IN PCOMMAND_PACKET Cmd,
  3010. IN PCHAR Text
  3011. );
  3012. VOID
  3013. SendCmdTrace(
  3014. IN ULONG Severity,
  3015. IN PCHAR Debsub,
  3016. IN ULONG uLineNo,
  3017. IN PCOMMAND_PACKET Cmd,
  3018. IN ULONG WStatus,
  3019. IN PCHAR Text
  3020. );
  3021. VOID
  3022. ReceiveCmdTrace(
  3023. IN ULONG Severity,
  3024. IN PCHAR Debsub,
  3025. IN ULONG uLineNo,
  3026. IN PCOMMAND_PACKET Cmd,
  3027. IN PCXTION Cxtion,
  3028. IN ULONG WStatus,
  3029. IN PCHAR Text
  3030. );
  3031. VOID
  3032. StageFileTrace(
  3033. IN ULONG Severity,
  3034. IN PCHAR Debsub,
  3035. IN ULONG uLineNo,
  3036. IN GUID *CoGuid,
  3037. IN PWCHAR FileName,
  3038. IN PULONGLONG pFileSize,
  3039. IN PULONG pFlags,
  3040. IN PCHAR Text
  3041. );
  3042. VOID
  3043. SetCxtionStateTrace(
  3044. IN ULONG Severity,
  3045. IN PCHAR Debsub,
  3046. IN ULONG uLineNo,
  3047. IN PCXTION Cxtion,
  3048. IN ULONG NewState
  3049. );
  3050. VOID
  3051. FrsPrintLongUStr(
  3052. IN ULONG Severity,
  3053. IN PCHAR Debsub,
  3054. IN ULONG uLineNo,
  3055. IN PWCHAR UStr
  3056. );
  3057. #endif // _FRSALLOC_