Source code of Windows XP (NT5)
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.

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