{$IfDef FPC}{$CodePage cp1251}{$EndIf FPC}
unit m3DBTools;
// --------------------------------------------------------------------------
// Родители: "m3DB" <<Unit>> MUID: (4742C9DB033A) :: "m3" <<Library>> MUID: (548712F60101) :: "Shared Delphi Low Level" <<Project>> MUID: (4ABCC25A0322)
// --------------------------------------------------------------------------
// Модуль: "w:\common\components\rtl\Garant\m3\m3DBTools.pas" GeneratorVersion: 1.0.0.883901
// Стереотип: "<<UtilityPack>>"
// Элемент модели: "m3DBTools" MUID: (5AEC481D0310)
// --------------------------------------------------------------------------
//#UC START# *5AEC481D0310beforeDefines*
//#UC END# *5AEC481D0310beforeDefines*
{$Include m3Define.inc}
interface
uses
l3IntfUses
, l3Ranges
, m3DBInterfaces
, Classes
, l3CoreInterfaces
, l3Types
, l3IntegerToIntegerMap
, SysUtils
, m3SearcherInterfaces
, l3Interfaces
, m3StorageInterfaces
, l3IntegerList
, l3CProtoObject
//#UC START# *5AEC481D0310intf_uses*
//#UC END# *5AEC481D0310intf_uses*
;
type
Tm3FilteredRange = class(Tl3CProtoObject, Im3DBRange)
private
f_Versions: Tl3IntegerToIntegerMap;
f_Other: Im3DBRange;
protected
function DB: Im3DB;
function Mul(const aRange: Im3DBRange): Im3DBRange;
{* Пересекает выборки. }
{$If NOT Defined(m3NoEVD)}
function Iterate(const aFilter: Im3TagGenerator;
aNeedWriteToBase: Boolean;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
{$IfEnd} // NOT Defined(m3NoEVD)
function IterateF(anAction: Tm3FilerAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer; overload;
function IterateF(anAction: Tm3DocumentAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer; overload;
function CopyTo(const aDB: Im3DB;
aMode: Tm3DBCopyMode = m3_cmRewrite;
const aParts: Tm3DocPartSet = m3_AllDocParts): Boolean;
{* переливает выборку в другую базу. }
procedure Cleanup; override;
{* Функция очистки полей объекта. }
procedure ClearFields; override;
public
constructor Create(aVersions: Tl3IntegerToIntegerMap;
const anOther: Im3DBRange); reintroduce;
class function MakePrim(aVersions: Tl3IntegerToIntegerMap;
const anOther: Im3DBRange): Im3DBRange; reintroduce;
class function Make(aVersions: Tl3IntegerToIntegerMap;
const anOther: Im3DBRange): Im3DBRange;
{$If NOT Defined(l3NoSRT)}
function SetRefTo(var thePlace: Tm3FilteredRange): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
{$IfEnd} // NOT Defined(l3NoSRT)
end;//Tm3FilteredRange
//#UC START# *5DA721C700ECci*
//#UC END# *5DA721C700ECci*
Tm3SubRange = class(Tl3CProtoObject, Im3DBRange)
private
f_MaxLen: Integer;
f_Other: Im3DBRange;
f_From: Integer;
f_Last: Integer;
protected
function DB: Im3DB;
function Mul(const aRange: Im3DBRange): Im3DBRange;
{* Пересекает выборки. }
{$If NOT Defined(m3NoEVD)}
function Iterate(const aFilter: Im3TagGenerator;
aNeedWriteToBase: Boolean;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
{$IfEnd} // NOT Defined(m3NoEVD)
function IterateF(anAction: Tm3FilerAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer; overload;
function IterateF(anAction: Tm3DocumentAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer; overload;
function CopyTo(const aDB: Im3DB;
aMode: Tm3DBCopyMode = m3_cmRewrite;
const aParts: Tm3DocPartSet = m3_AllDocParts): Boolean;
{* переливает выборку в другую базу. }
procedure Cleanup; override;
{* Функция очистки полей объекта. }
procedure ClearFields; override;
public
constructor Create(aFrom: Integer;
aMaxLen: Integer;
const anOther: Im3DBRange); reintroduce;
class function Make(aFrom: Integer;
aMaxLen: Integer;
const anOther: Im3DBRange): Im3DBRange; reintroduce;
{$If NOT Defined(l3NoSRT)}
function SetRefTo(var thePlace: Tm3SubRange): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
{$IfEnd} // NOT Defined(l3NoSRT)
public
property Last: Integer
read f_Last;
//#UC START# *5DA721C700ECpubl*
//#UC END# *5DA721C700ECpubl*
end;//Tm3SubRange
function m3ImportDocument(const aDB: Im3DB;
anIn: TStream;
anID: Integer): Boolean; overload;
function m3ImportDocument(const aDB: Im3DB;
const anIn: AnsiString;
anID: Integer): Boolean; overload;
function m3IndexRange(const aRange: Im3DBRange;
const anIndexName: Il3CString;
aNeedWriteVersions: Boolean;
aFilesMeter: Tl3ProgressProc;
const aDB: Im3DB): Integer;
function m3BuildIndexDelta(const aDB: Im3DB;
const anIndexName: Il3CString;
aFilesMeter: Tl3ProgressProc;
aVersions: Tl3IntegerToIntegerMap = nil): Integer;
function m3DBBuildIndexDelta(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aNestedCall: Boolean;
aForceFullIndex: Boolean;
aFrom: Integer = 0;
aTo: Integer = High(Integer)): Boolean;
function m3BuildFullIndex(const aDB: Im3DB;
const anIndexName: Il3CString;
aFilesMeter: Tl3ProgressProc;
const aDBHelper: Im3DBHelper;
var aDeltas: Im3FilesEnumerable;
aForceFullIndex: Boolean;
aFrom: Integer;
aTo: Integer): Integer;
procedure m3LoadVersionsFromStream(aVersions: Tl3IntegerToIntegerMap;
const aStream: IStream);
procedure m3WriteVersionsToStream(const aVersions: Im3IndexedVersions;
const aStream: IStream);
procedure m3WriteVersions(const aStorage: Im3IndexedStorage;
const aVersions: Im3IndexedVersions);
procedure m3MergeFromDumper(var aDumper: Im3IndexDumper;
const anUpdateName: Il3CString;
aWriteVersions: Boolean;
aFilesMeter: Tl3ProgressProc;
const aBaseName: TFileName);
procedure m3CreateSummary(const aStorage: Im3IndexedStorage);
function m3DBMergeIndexDeltas(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc): Boolean; overload;
function m3DBIndexUpdated(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aForceMerge: Boolean): Boolean;
function m3DBBuildAndMergeIndexDeltas(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc): Boolean;
function m3DBMergeIndexDeltas(const aDBHelper: Im3DBHelper;
var aDeltas: Im3FilesEnumerable;
aFilesMeter: Tl3ProgressProc): Boolean; overload;
function m3DBUpdateIndex(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc): Boolean;
function m3ReadModified(const aStorage: Im3IndexedStorage): Il3RangeEnumerable;
procedure m3WriteModified(const aStorage: Im3IndexedStorage;
const aModified: Il3RangeEnumerable;
aTimeStamp: TDateTime); overload;
procedure m3DBWaitIndexer;
function m3DBIndexDoc(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aDocNum: Integer): Boolean;
function m3DBIndexDocs(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aDocNums: Tl3IntegerList): Boolean;
procedure m3DBIndexDocAsync(const aBaseName: TFileName;
aDocNum: Integer);
procedure m3DBNeedIndexDoc(const aBaseName: TFileName;
aDocNum: Integer);
procedure m3DBIndexUpdatedAsync(const aBaseName: TFileName);
procedure m3SetInternalIDtoExternalIDLink(const aBaseName: TFileName;
anInternalID: Integer;
anExternalID: Integer);
{* Устанавливает связь между внутренним номером документа и внешним
https://mdp.garant.ru/pages/viewpage.action?pageId=892273772 }
procedure m3WriteModified(const aStorage: Im3IndexedStorage;
const aModified: Il3RangeEnumerable); overload;
procedure m3WriteStringToDocument(const aDB: Im3DB;
aDocID: Integer;
anAttrID: Integer;
const aString: Tl3WString);
var g_IndexByParts: Boolean = True;
{* Индексировать основной индекс КУСКАМИ }
var g_IndexOnlyAttributes: Boolean = False;
{* Индексировать ТОЛЬКО атрибуты }
//#UC START# *5AEC481D0310publ*
var g_InBuildFullIndex: Boolean = false;
var g_MergeOnlyAttributes: Boolean = false;
//#UC END# *5AEC481D0310publ*
implementation
uses
l3ImplUses
, m3DBHelper
, m3DocumentAddressCachedStore
, m3DocumentAddressStore
, m3DocumentAddressCachedStoreProxy
, m3IDRangeListPrim
, m3RangedDocumentsList
, m3ExternalIDtoInternalIDMap
//#UC START# *5AEC481D0310impl_uses*
{$If NOT Defined(Linux)}
, Windows
{$Else NOT Defined(Linux)}
// using l3LinWindows instead of Windows
, l3LinWindows
{$IfEnd} // NOT Defined(Linux)
, Math
, StrUtils
, DateUtils
{$If NOT Defined(Linux)}
, ActiveX
{$Else NOT Defined(Linux)}
// using l3LinActiveX instead of ActiveX
, l3LinActiveX
{$IfEnd} // NOT Defined(Linux)
{$If NOT Defined(Linux)}
, ComObj
{$Else NOT Defined(Linux)}
// using l3LinComObj instead of ComObj
, l3LinComObj
{$IfEnd} // NOT Defined(Linux)
//, l3CoreInterfaces
, m3HashElements
, m3StorageTools
, l3Chars
, l3String
, l3StringEx
, l3Date
, l3Enumerators
, l3StringsEnumerator
, l3FileUtils
, m3DBActions
, m2COMLib
, l3Stream
//, SysUtils
, m3EvdDocumentIndexBuilder
, m3StgMgr
, m4DB
, m3DB
, l3Filer
, l3MemUtils
, l3Base
, m2HASLib
, m3BackupTools
, m3StorageService
, l3Prg
, k2Tags
, k2Attributes
, m3SplittedFileStream
, m3WordAddress
, m3DocumentAddress
, m3IdxCla
, m3IndexSearcherFilteredResult
, m3IndexConst
, m3IndexDumper
, m3IndexDumperJoin
, m3StorageElementIDList
, m3StorageHolderList
, m3BaseStream
, l3StoreInterfaces
, l3SysUtils
//, m3DocumentAddressStore
//, m3DocumentAddressCachedStore
, m3Const
, m3Endings
, m3DBDocumentPart
, m3Exceptions
, k2TagGen
, m3EvdDocumentAttrsIndexBuilder
, l3TimeService
, m3AttrIndexDumper
, m3AttrIndexDumperJoin
, m3AttrIndexInterfaces
, m3AttrIndexSearcher
, m3DocumentAttrIndexBuilder
, m3IndexerTypes
, m3AttrID
, l3BaseStream
, m3ProxyIndexStream
;
type
Tm3DBIndexDocThread = class(TThread)
private
f_BaseName : TFileName;
f_DocNum : Integer;
f_DocNums : Tl3IntegerList;
protected
procedure Execute; override;
public
constructor Create(const aBaseName : TFileName; aDocNum : Integer);
class procedure Run(const aBaseName : TFileName; aDocNum : Integer);
destructor Destroy; override;
end;//Tm3DBIndexDocThread
var
g_IndexDocThreadWaitAdded : Boolean = false;
g_IndexDocThread : Tm3DBIndexDocThread = nil;
g_IndexDocThreadstarted : Boolean = false;
type
Tm3DBIndexUpdatedThread = class(TThread)
private
f_BaseName : TFileName;
protected
procedure Execute; override;
public
constructor Create(const aBaseName : TFileName);
end;//Tm3DBIndexUpdatedThread
const
cFakeConst = 1
//#UC END# *5AEC481D0310impl_uses*
;
function m3ImportDocument(const aDB: Im3DB;
anIn: TStream;
anID: Integer): Boolean;
//#UC START# *5AFD5D9D00BB_5AEC481D0310_var*
var
l_Doc : Im3DBDocument;
l_Part : Im3DBDocumentPart;
l_Info : Tm3DBDocumentInfo;
l_Out : IStream;
//#UC END# *5AFD5D9D00BB_5AEC481D0310_var*
begin
//#UC START# *5AFD5D9D00BB_5AEC481D0310_impl*
l_Doc := aDB.GetDocument(anID);
l_Out := l_Doc.Open(m3_saReadWrite);
try
Result := l3CopyStream(anIn, l_Out);
finally
l_Out := nil;
end;//try..finally
l_Part := l_Doc.GetVersion;
l_Info := l_Part.Info;
l_Info.rIndexID := 1;
l_Part.Info := l_Info;
//#UC END# *5AFD5D9D00BB_5AEC481D0310_impl*
end;//m3ImportDocument
function m3ImportDocument(const aDB: Im3DB;
const anIn: AnsiString;
anID: Integer): Boolean;
//#UC START# *5AFD622403B9_5AEC481D0310_var*
var
l_In : Tl3FileStream;
//#UC END# *5AFD622403B9_5AEC481D0310_var*
begin
//#UC START# *5AFD622403B9_5AEC481D0310_impl*
l_In := Tl3FileStream.Create(anIn, l3_fmRead);
try
Result := m3ImportDocument(aDB, l_In, anID);
finally
FreeAndNil(l_In);
end;//try..finally
//#UC END# *5AFD622403B9_5AEC481D0310_impl*
end;//m3ImportDocument
function m3IndexRange(const aRange: Im3DBRange;
const anIndexName: Il3CString;
aNeedWriteVersions: Boolean;
aFilesMeter: Tl3ProgressProc;
const aDB: Im3DB): Integer;
//#UC START# *5AFEA7650018_5AEC481D0310_var*
procedure DoDoIndex;
var
l_IndexRoot : Im3IndexedStorage;
procedure DoIndex;
var
l_Progress : Il3Progress;
l_Builder : Tm3EvdDocumentIndexBuilder;
l_Gen : Tk2TagGenerator;
begin//DoIndex
l_Progress := nil;
try
if Assigned(aFilesMeter) then
l_Progress := Tl3ProgressIndicator.Make(aFilesMeter);
if g_IndexOnlyAttributes then
l_Builder := nil
else
l_Builder := Tm3EvdDocumentIndexBuilder.Create(l_IndexRoot, aNeedWriteVersions, l_Progress);
try
l_Gen := nil;
try
l_Builder.SetRefTo(l_Gen);
Tm3EvdDocumentAttrsIndexBuilder.SetTo(l_Gen, Il3CString_ToFileName(anIndexName), aNeedWriteVersions, nil{aDB});
//Tm3EvdDocumentAttrsIndexBuilder.SetTo(l_Gen, Il3CString_ToFileName(anIndexName), aNeedWriteVersions, aDB);
if (l_IndexRoot <> nil) then
m3CreateSummary(l_IndexRoot);
l_IndexRoot := nil;
if (aDB = nil) then
Result := m4IndexRange(aRange, l_Gen)
else
if g_InBuildFullIndex then
Result := m4IndexRange(aRange, l_Gen)
else
begin
aDB.Start(m3_saRead);
//aDB.Start(m3_saReadWrite);
try
Result := m4IndexRange(aRange, l_Gen);
finally
aDB.Finish;
end;//try..finally
//Result := m4IndexRange(aRange, l_Gen);
end;//aDB = nil
finally
FreeAndNil(l_Gen);
end;//try..finally
finally
FreeAndNil(l_Builder);
end;//try..finally
finally
l_Progress := nil;
end;//try..finally
end;//DoIndex
{$IfDef m3UseProxyIndexStream}
{$Define m3LocUseProxyIndexStream}
{$EndIf m3UseProxyIndexStream}
var
l_Name : TFileName;
{$IfDef m3LocUseProxyIndexStream}
l_Temp : Tl3Stream;
l_H : Im3StorageHolder;
{$EndIf m3LocUseProxyIndexStream}
begin//DoDoIndex
l_IndexRoot := nil;
try
if not g_IndexOnlyAttributes then
begin
l_Name := Il3CString_ToFileName(anIndexName);
m3Endings.InitEndings(ExtractFilePath(l_Name));
{$IfNDef m3UseVersionedIndexDeltas}
Tm3StorageManager.DeleteStorageFile(l_Name);
{$EndIf m3UseVersionedIndexDeltas}
{$IfDef m3LocUseProxyIndexStream}
if not Tm3StorageService.Instance.UseSplitted then
begin
l_Temp := Tm3ProxyIndexStream.Create(l_Name);
try
l_H := Tm3FullModeExclusiveStorageManager.MakeInterface(l_Temp, c_m3UseVersionedIndexDeltas, def_FullModeStorageUseCompression);
try
l_IndexRoot := l_H.Storage;
finally
l_H := nil;
end;//try..finally
finally
FreeAndNil(l_Temp);
end;//try..finally
end//not Tm3StorageService.Instance.UseSplitted
else
l_IndexRoot := Tm3FullModeExclusiveStorageManager.MakeInterface(l_Name, c_m3UseVersionedIndexDeltas);
{$Else m3LocUseProxyIndexStream}
l_IndexRoot := Tm3FullModeExclusiveStorageManager.MakeInterface(l_Name, c_m3UseVersionedIndexDeltas);
{$EndIf m3LocUseProxyIndexStream}
end;//not g_IndexOnlyAttributes
{$IfNDef m3UseVersionedIndexDeltas}
if (l_IndexRoot <> nil) then
l_IndexRoot.ClearAll;
{$EndIf m3UseVersionedIndexDeltas}
if (aDB = nil) then
DoIndex
else
if g_InBuildFullIndex then
DoIndex
else
begin
aDB.Start(m3_saRead);
//aDB.Start(m3_saReadWrite);
try
DoIndex;
finally
aDB.Finish;
end;//try..finally
end;//aDB = nil
finally
l_IndexRoot := nil;
end;//try..finally
end;//DoDoIndex
//#UC END# *5AFEA7650018_5AEC481D0310_var*
begin
//#UC START# *5AFEA7650018_5AEC481D0310_impl*
Result := -1;
Assert(aRange <> nil);
try
DoDoIndex;
// - специально выделено, чтобы интерфейсы отпускались
except
Result := -1;
Tm3StorageManager.DeleteStorageFile(anIndexName);
// - удаляем "провисший" файл
raise;
end;//try..except
//#UC END# *5AFEA7650018_5AEC481D0310_impl*
end;//m3IndexRange
function m3BuildIndexDelta(const aDB: Im3DB;
const anIndexName: Il3CString;
aFilesMeter: Tl3ProgressProc;
aVersions: Tl3IntegerToIntegerMap = nil): Integer;
//#UC START# *5AFEAABE01E5_5AEC481D0310_var*
var
l_Range : Im3DBRange;
//#UC END# *5AFEAABE01E5_5AEC481D0310_var*
begin
//#UC START# *5AFEAABE01E5_5AEC481D0310_impl*
Result := -1;
l_Range := nil;
try
//l_Range := aDB.ModifiedFiles;
l_Range := aDB.IndexedFiles.Mul(aDB.ModifiedFiles);
if (aVersions <> nil) AND not aVersions.Empty then
l_Range := Tm3FilteredRange.Make(aVersions, l_Range);
Result := m3IndexRange(l_Range, anIndexName, true, aFilesMeter, aDB);
finally
l_Range := nil;
end;//try..finally
//#UC END# *5AFEAABE01E5_5AEC481D0310_impl*
end;//m3BuildIndexDelta
function m3DBBuildIndexDelta(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aNestedCall: Boolean;
aForceFullIndex: Boolean;
aFrom: Integer = 0;
aTo: Integer = High(Integer)): Boolean;
//#UC START# *5B07D36103E7_5AEC481D0310_var*
var
l_Versions : Tl3IntegerToIntegerMap;
procedure LoadVersions(const aName: String);
var
l_S : Im3IndexedStorage;
l_V : Il3Stream;
begin//LoadVersions
l_S := Tm3ReadModeStorageManager.MakeInterface(aName{, false});
try
if (l_S <> nil) then
begin
l_V := m3COMOpenStream(l_S,
l3PCharLen('versions'),
m3_saRead,
false);
try
if (l_V <> nil) then
begin
l_S := nil;
// - типа он нам больше не нужен
if (l_Versions = nil) then
l_Versions := Tl3IntegerToIntegerMap.Create;
m3LoadVersionsFromStream(l_Versions, l_V.As_IStream);
end;//l_V <> nil
finally
l_V := nil;
end;//try..finally
end;//l_S <> nil
finally
l_S := nil;
end;//try..finally
end;//LoadVersions
function MakeDB(const aName: String): Im3DB;
begin
Result := Tm3DB.Make(aName,
//cbMakeCopy.Checked AND cbFromOld.Checked,
nil,//Yield,
nil,//FileMeter.ProgressProc_ev,
aFilesMeter,//FilesMeter.ProgressProc_ev,
nil,//FilesProcessed,
nil //lProgressor.FilesProcessedExProc//FilesProcessedEx
);
end;
var
l_BaseName : String;
l_IndexName : Il3CString;
l_PrevIndexName : Il3CString;
l_NeedDelete : Boolean;
l_DBHelper : Im3DBHelper;
l_E : Im3FilesEnumerable;
var
l_NeedExit : Boolean;
procedure DoBuildFullIndex;
var
l_DB : Im3DB;
begin//DoBuildFullIndex
l_NeedExit := false;
//l_FlagFiler.WriteLn(l_IndexName);
l_DB := MakeDB(l_BaseName);
try
l_NeedDelete := m3BuildFullIndex(l_DB, l_IndexName, aFilesMeter, l_DBHelper, l_E, aForceFullIndex, aFrom, aTo) <= 0;
l_NeedDelete := false;
if not Tm3StorageManager.StorageFileExists(l_BaseName + m3_cExchangeExt) then
// - нету переменной части - дельту строить не надо
begin
Result := true;
l_NeedExit := true;
Exit;
end;//not Tm3StorageManager.StorageFileExists(l_BaseName + m3_cExchangeExt)
finally
l_DB := nil;
end;//try..finally
//l_E := l_DBHelper.GetIndexDeltasFiles;
// - перечитываем из-за m3BuildFullIndex
end;//DoBuildFullIndex
procedure DoBuildIndexDelta;
var
l_DB : Im3DB;
l_US : Boolean;
l_T1, l_T2 : TDateTime;
begin//DoBuildIndexDelta
l_DB := MakeDB(l_BaseName);
try
if not aNestedCall then
begin
l_T1 := NullDate;
l_T2 := NullDate;
l_T1 := Tm3StorageManager.StorageFileDateTime(l_BaseName + m3_cExchangeExt);
if (l_PrevIndexName <> nil) then
l_T2 := Tm3StorageManager.StorageFileDateTime(l_PrevIndexName);
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
if SameValue(l_T1, NullDate) OR
SameValue(l_T2, NullDate) OR
((DaysBetween(l_T1, l_T2) > 0) AND (CompareValue(l_T1, l_T2) > 0))
then
l_NeedDelete := m3BuildIndexDelta(l_DB, l_IndexName, aFilesMeter, nil) <= 0
else
l_NeedDelete := m3BuildIndexDelta(l_DB, l_IndexName, aFilesMeter, l_Versions) <= 0;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end//not aNestedCall
else
begin
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
l_NeedDelete := m3BuildIndexDelta(l_DB, l_IndexName, aFilesMeter, l_Versions) <= 0;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end;//not aNestedCall
finally
l_DB := nil;
end;//try..finally
end;//DoBuildIndexDelta
var
l_Files : Im3FilesEnumerator;
//#UC END# *5B07D36103E7_5AEC481D0310_var*
begin
//#UC START# *5B07D36103E7_5AEC481D0310_impl*
Result := false;
try
Assert(aBaseName <> '');
l_Versions := nil;
try
l_NeedDelete := false;
l_BaseName := Tm3SplittedFileStream.NormalizeFileName(aBaseName);
l_BaseName := ChangeFileExt(l_BaseName, '');
//l_Path := ExtractFilePath(l_BaseName);
l_DBHelper := Tm3DBHelper.Make(l_BaseName);
try
Assert(l_DBHelper <> nil);
l_E := l_DBHelper.GetIndexDeltasFiles;
if not aNestedCall then
begin
if not l_DBHelper.LockDeltas(l_E) then
begin
Result := false;
Exit;
end;//not l_DBHelper.Lock
end;//not aNestedCall
try
l_IndexName := l_DBHelper.IndexName;
l_PrevIndexName := nil;
if not aNestedCall then
begin
if aForceFullIndex
OR not Tm3StorageManager.StorageFileExists(l_IndexName)
then
// - тут надо бы построить ПОЛНЫЙ индекс
begin
DoBuildFullIndex;
if l_NeedExit then
Exit;
end;//Tm3StorageManager.StorageFileExists(l_IndexName)
end;//not aNestedCall
//l_E := l_DBHelper.GetIndexDeltasFiles;
if (l_E <> nil) then
begin
l_Files := l_E.GetEnumerator;
try
Assert(l_Files <> nil);
while l_Files.MoveNext do
begin
l_IndexName := l_Files.Current.AsCStr;
l_PrevIndexName := l_IndexName;
LoadVersions(Il3CString_ToFileName(l_IndexName));
end;//while l_Files.MoveNext
finally
l_Files := nil;
end;//try..finally
end;//l_E <> nil
l_IndexName := l_DBHelper.NewIndexDeltaName(l_E);
//l_FlagFiler.WriteLn(l_IndexName);
//Exit;
try
DoBuildIndexDelta;
except
Result := false;
Tm3StorageManager.DeleteStorageFile(l_IndexName);
// - удаляем "провисший" файл
raise;
end;//try..except
if l_NeedDelete then
Tm3StorageManager.DeleteStorageFile(l_IndexName)
else
l_DBHelper.AddNewIndexDeltaName(l_IndexName, l_E);
finally
if not aNestedCall then
l_DBHelper.UnlockDeltas;
end;//try..finally
finally
l_DBHelper := nil;
end;//try..finally
finally
FreeAndNil(l_Versions);
end;//try..finally
Result := true;
except
on E: Exception do
begin
l3System.Exception2Log(E);
Result := false;
end;//on E: Exception
else
Result := false;
end;//try..except
//#UC END# *5B07D36103E7_5AEC481D0310_impl*
end;//m3DBBuildIndexDelta
function m3BuildFullIndex(const aDB: Im3DB;
const anIndexName: Il3CString;
aFilesMeter: Tl3ProgressProc;
const aDBHelper: Im3DBHelper;
var aDeltas: Im3FilesEnumerable;
aForceFullIndex: Boolean;
aFrom: Integer;
aTo: Integer): Integer;
//#UC START# *5B07DA9600E1_5AEC481D0310_var*
const
{$IfDef nsTest}
cLen = 10{50};
// - так как в базе всего 70+ документов
{$Else nsTest}
cLen = 150000;
//cLen = 40000{20000}{100000};
{$EndIf nsTest}
var
l_Range : Im3DBRange;
l_SubRange : Tm3SubRange;
l_From : Integer;
l_Count : Integer;
l_IndexName : Il3CString;
l_US : Boolean;
l_InBuildFullIndex: Boolean;
//l_E : Im3FilesEnumerable;
//#UC END# *5B07DA9600E1_5AEC481D0310_var*
begin
//#UC START# *5B07DA9600E1_5AEC481D0310_impl*
Result := -1;
l_InBuildFullIndex := g_InBuildFullIndex;
try
{$IfDef m3DBCheck}
g_InBuildFullIndex := true;
{$Else m3DBCheck}
if aForceFullIndex then
g_InBuildFullIndex := true
else
g_InBuildFullIndex := false;
//g_InBuildFullIndex := true;
{$EndIf m3DBCheck}
l_Range := nil;
try
if not aForceFullIndex
AND
{$IfDef m3IndexByParts}not g_IndexByParts{false}{$Else}true{$EndIf} then
begin
l_Range := aDB.IndexedFiles;
Result := m3IndexRange(l_Range, anIndexName, false, aFilesMeter, aDB);
end//not g_IndexByParts
else
begin
//l_E := aDBHelper.GetIndexDeltasFiles;
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
Result := 0;
l_From := Max(0, aFrom);
while (l_From < High(l_From)) do
begin
l_Range := aDB.IndexedFiles(1, l_From);
try
l_SubRange := Tm3SubRange.Create(l_From, cLen, l_Range);
try
l_IndexName := anIndexName;
if aForceFullIndex
OR Tm3StorageManager.StorageFileExists(l_IndexName) then
begin
l_IndexName := aDBHelper.NewIndexDeltaName(aDeltas);
l_Count := m3IndexRange(l_SubRange, l_IndexName, false, aFilesMeter, aDB);
if (l_Count < 0) then
l_Count := 0;
if (l_Count <= 0) then
Tm3StorageManager.DeleteStorageFile(l_IndexName)
else
aDBHelper.AddNewIndexDeltaName(l_IndexName, aDeltas);
end//Tm3StorageManager.StorageFileExists(l_IndexName)
else
begin
l_Count := m3IndexRange(l_SubRange, l_IndexName, false, aFilesMeter, aDB);
if (l_Count < 0) then
l_Count := 0;
if (l_Count <= 0) then
Tm3StorageManager.DeleteStorageFile(l_IndexName);
end;//Tm3StorageManager.StorageFileExists(l_IndexName)
Inc(Result, l_Count);
if (l_SubRange.Last <= l_From) then
break;
{$If not Defined(Linux) OR not Defined(nsTest)}
l3System.Msg2Log('Indexed: ' + Il3CString_StrEx(l_IndexName) + ' ' + IntToStr(l_From) + ' : ' + IntToStr(l_SubRange.Last));
{$IfEnd}
l_From := l_SubRange.Last;
if (l_From >= aTo) then
break;
finally
FreeAndNil(l_SubRange);
end;//try..finally
finally
l_Range := nil;
end;//try..finally
end;//while
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end;//not g_IndexByParts
finally
l_Range := nil;
end;//try..finally
finally
g_InBuildFullIndex := l_InBuildFullIndex;
end;//try..finally
//#UC END# *5B07DA9600E1_5AEC481D0310_impl*
end;//m3BuildFullIndex
procedure m3LoadVersionsFromStream(aVersions: Tl3IntegerToIntegerMap;
const aStream: IStream);
//#UC START# *5B07EABC001C_5AEC481D0310_var*
var
l_ID : Integer;
l_Version : Integer;
l_Return: HRESULT;
l_Read : Integer;
l_Index : Integer;
//#UC END# *5B07EABC001C_5AEC481D0310_var*
begin
//#UC START# *5B07EABC001C_5AEC481D0310_impl*
Assert(aStream <> nil);
while true do
begin
l_Return := aStream.Read(@l_ID, SizeOf(l_ID), @l_Read);
if (l_Return = S_FALSE) then
break;
OleCheck(l_Return);
if (l_Read <> SizeOf(l_ID)) then
break;
l_Return := aStream.Read(@l_Version, SizeOf(l_Version), @l_Read);
if (l_Return = S_FALSE) then
break;
OleCheck(l_Return);
if (l_Read <> SizeOf(l_Version)) then
break;
if (l_Version = Cm3ConstVersion) then
l_Version := 0;
if not aVersions.Has(l_ID, l_Index) then
aVersions.Insert(l_Index, l_ID, l_Version)
else
begin
aVersions.ItemSlot(l_Index)^.rValue := l_Version;
end;//not l_Versions.Has(l_ID, l_Index)
end;//while true
//#UC END# *5B07EABC001C_5AEC481D0310_impl*
end;//m3LoadVersionsFromStream
procedure m3WriteVersionsToStream(const aVersions: Im3IndexedVersions;
const aStream: IStream);
//#UC START# *5B2E22830040_5AEC481D0310_var*
var
//l_Index : Integer;
l_It : Tl3IntegerToIntegerMap_Enumerator;
l_ID : Integer;
l_Version : Integer;
//#UC END# *5B2E22830040_5AEC481D0310_var*
begin
//#UC START# *5B2E22830040_5AEC481D0310_impl*
if (aVersions <> nil) then
begin
l_It := aVersions.GetEnumerator;
if (l_It = nil) then
Exit;
while l_It.MoveNext do
//for l_Index := 0 to Pred(aVersions.Count) do
begin
//with aVersions.ItemSlot(l_Index)^ do
begin
l_ID := l_It.pCurrent^.rKey;
l_Version := l_It.pCurrent^.rValue;
m2COMWriteBuffer(aStream, l_ID, SizeOf(l_ID));
m2COMWriteBuffer(aStream, l_Version, SizeOf(l_Version));
end;//with aVersions.ItemSlot(l_Index)^
end;//for l_Index
end;//aVersions <> nil
//#UC END# *5B2E22830040_5AEC481D0310_impl*
end;//m3WriteVersionsToStream
procedure m3WriteVersions(const aStorage: Im3IndexedStorage;
const aVersions: Im3IndexedVersions);
//#UC START# *5B2E2F0E02BF_5AEC481D0310_var*
var
l_Versions : IStream;
//#UC END# *5B2E2F0E02BF_5AEC481D0310_var*
begin
//#UC START# *5B2E2F0E02BF_5AEC481D0310_impl*
l_Versions := m3COMOpenStream(aStorage,
l3PCharLen('versions'),
m3_saWrite,
//m3_saReadWrite,
true{false}).As_IStream;
try
if (aVersions <> nil) then
begin
m3WriteVersionsToStream(aVersions, l_Versions);
end;//aVersions <> nil
finally
l_Versions := nil;
end;//try..finally
//#UC END# *5B2E2F0E02BF_5AEC481D0310_impl*
end;//m3WriteVersions
procedure m3MergeFromDumper(var aDumper: Im3IndexDumper;
const anUpdateName: Il3CString;
aWriteVersions: Boolean;
aFilesMeter: Tl3ProgressProc;
const aBaseName: TFileName);
//#UC START# *5B2E3DB902C7_5AEC481D0310_var*
var
l_OutHash : Im3IndexedStorage;
l_HashInfo : IStream;
l_StatStream : IStream;
l_Start : Cardinal;
function DoHash(const aHashElement: Im3IndexHashElement): Boolean;
var
l_HashStorage : Im3IndexedStorage;
function DoWord(aWord: Tl3PrimString): Boolean;
var
l_OutWordStream : Im3DocumentAddressStore;
//l_Address : Tm3DocumentAddress;
//l_Result : Im3IndexSearcherResult;
l_AE : Im3AddressesEnumerable;
begin//DoWord
Result := true;
if Assigned(aFilesMeter) then
aFilesMeter(piCurrent, aHashElement.ID, l3StrEx(aWord.AsWStr));
l_OutWordStream := nil;
try
//l_Result := nil;
if (aWord.AsString = '2') then
l_AE := aHashElement.LemmaAddresses(aWord)
else
l_AE := aHashElement.LemmaAddresses(aWord);
if (l_AE <> nil) then
begin
l_OutWordStream := Tm3DocumentAddressCachedStoreProxy.Make(l_HashInfo, l_OutHash, aHashElement.ID, aWord, l_StatStream, 0, l_HashStorage);
Assert(l_OutWordStream <> nil);
l_AE.WriteTo(l_OutWordStream);
end;//l_AE <> nil
(* if (l_AE <> nil) then
l_Result := l_AE.GetEnumerator;
l_AE := nil; // - типа уже можно отпустить
if (l_Result <> nil) then
begin
try
l_OutWordStream := Tm3DocumentAddressCachedStoreProxy.Make(l_HashInfo, l_OutHash, aHashElement.ID, aWord, l_StatStream, 0, l_HashStorage);
Assert(l_OutWordStream <> nil);
while l_Result.GetAddress(l_Address, 0) do
begin
l_OutWordStream.PutAddress(@l_Address, SizeOf(l_Address));
end;//while l_Result.GetAddress
finally
l_Result := nil;
end;//try..finally
end;//l_Result <> nil*)
finally
l_OutWordStream := nil;
end;//try..finally
end;//DoWord
const
cTimeDelta = 20 * 60 * 1000;
var
l_LemmasE : Im3StringsEnumerable;
l_Lemmas : Im3StringsEnumerator;
l_TimeDelta : Int64;
begin//DoHash
Result := true;
l_LemmasE := nil;
l_Lemmas := nil;
try
l_LemmasE := aHashElement.Lemmas;
if (l_LemmasE <> nil) then
begin
l_Lemmas := l_LemmasE.GetEnumerator;
l_LemmasE := nil;
if (l_Lemmas <> nil) then
begin
l_HashStorage := nil;
//l_HashStorage := m3COMOpenStorage(l_OutHash, aHashElement.ID, m3_saReadWrite, true);
try
if Assigned(aFilesMeter) then
aFilesMeter(piCurrent, aHashElement.ID, '');
while l_Lemmas.MoveNext do
DoWord(l_Lemmas.Current);
finally
l_HashStorage := nil;
end;//try..finally
end;//l_Lemmas <> nil
end;//l_LemmasE <> nil
finally
l_Lemmas := nil;
end;//try..finally
l_TimeDelta := cTimeDelta;
{$IfNDef nsTest}
if (l3Date.DayOfWeek(SysUtils.Date) <> l3Date.Sunday)
AND (l3Date.DayOfWeek(SysUtils.Date) <> l3Date.Saturday) then
begin
l_TimeDelta := cTimeDelta div 2;
if (l_TimeDelta <= 1000) then
l_TimeDelta := cTimeDelta;
end;//l3Date.DayOfWeek(SysUtils.Date) <> l3Date.Sunday
{$EndIf nsTest}
if l3IsTimeElapsed(l_Start, l_TimeDelta) then
begin
// - здесь будем новые дельты строить
if (aBaseName <> '') then
begin
l3System.Msg2Log('Здесь будем новые дельты строить: ' + aBaseName);
m3DBBuildIndexDelta(aBaseName, nil, true, false{aForceFullIndex});
{$If Defined(nsTest) OR Defined(m3DBCheck)}
Tm3StorageHolderList.DropAllFiles;
// - давайте всё отпустим, чтобы например с ЕО не подраться
{$IfEnd}
l3System.Msg2Log('Закончили строить новые дельты: ' + aBaseName);
end;//aBaseName <> ''
l_Start := GetTickCount;
// - новая точка отсчёта
end;//l3IsTimeElapsed(l_Start, l_TimeDelta)
end;//DoHash
var
l_OutIndex: Im3IndexedStorage;
procedure CreateHashInfo;
begin//CreateHashInfo
l_HashInfo := m3COMOpenStream(l_OutIndex,
l3PCharLen(AnsiString(m3HashInfoName)),
m3_saWrite,
true).As_IStream;
l_StatStream := m3COMOpenStream(l_OutIndex,
l3PCharLen(AnsiString(m3StatStreamName)),
m3_saWrite,
true).As_IStream;
end;//CreateHashInfo
procedure WriteRange;
var
l_St : Il3Stream;
begin//WriteRange
l_St := m3COMOpenStream(l_OutIndex,
l3PCharLen('range'),
m3_saWrite,
true,
false);
try
if (l_St <> nil) then
aDumper.Range.WriteTo(l_St.As_IStream);
finally
l_St := nil;
end;//try..finally
end;//WriteRange
{$IfDef m3UseProxyIndexStream}
{$Define m3LocUseProxyIndexStream}
{$EndIf m3UseProxyIndexStream}
var
l_Enum : Im3IndexHashElementEnumerator;
l_UpdateName : String;
{$IfDef m3LocUseProxyIndexStream}
l_Temp : Tl3Stream;
l_H : Im3StorageHolder;
{$EndIf m3LocUseProxyIndexStream}
//#UC END# *5B2E3DB902C7_5AEC481D0310_var*
begin
//#UC START# *5B2E3DB902C7_5AEC481D0310_impl*
l_UpdateName := Il3CString_ToFileName(anUpdateName);
{$IfNDef m3UseVersionedIndexDeltas}
if Tm3StorageManager.StorageFileExists(l_UpdateName) then
Tm3StorageManager.DeleteStorageFile(l_UpdateName);
{$EndIf m3UseVersionedIndexDeltas}
{$IfDef m3LocUseProxyIndexStream}
if not Tm3StorageService.Instance.UseSplitted then
begin
l_Temp := Tm3ProxyIndexStream.Create(l_UpdateName);
try
l_H := Tm3FullModeExclusiveStorageManager.MakeInterface(l_Temp, c_m3UseVersionedIndexDeltas, def_FullModeStorageUseCompression);
try
l_OutIndex := l_H.Storage;
finally
l_H := nil;
end;//try..finally
finally
FreeAndNil(l_Temp);
end;//try..finally
end//not Tm3StorageService.Instance.UseSplitted
else
l_OutIndex := Tm3FullModeExclusiveStorageManager.MakeInterface(l_UpdateName, c_m3UseVersionedIndexDeltas);
{$Else m3LocUseProxyIndexStream}
l_OutIndex := Tm3FullModeExclusiveStorageManager.MakeInterface(l_UpdateName, c_m3UseVersionedIndexDeltas);
{$EndIf m3LocUseProxyIndexStream}
try
if Assigned(aFilesMeter) then
aFilesMeter(piStart, Cm2HASDefCount, 'Обновление индекса: ' + ExtractFileName(l_UpdateName));
try
m3CreateSummary(l_OutIndex);
if Assigned(aFilesMeter) then
aFilesMeter(piCurrent, 0, 'Запись списка документов');
m3WriteModified(l_OutIndex, aDumper.ModifiedDocuments, aDumper.TimeStamp);
if aWriteVersions then
begin
if Assigned(aFilesMeter) then
aFilesMeter(piCurrent, 0, 'Запись версий документов');
m3WriteVersions(l_OutIndex, aDumper.IndexedVersions);
end;//aWriteVersions
CreateHashInfo;
WriteRange;
try
l_OutHash := m3CreateHashData(l_OutIndex, l3PCharLen(AnsiString(m3HashDataName)));
try
l_OutIndex := nil; // - типа можно отпустить
if Assigned(aFilesMeter) then
aFilesMeter(piCurrent, 0, 'Обновление индекса: ' + ExtractFileName(l_UpdateName));
l_Enum := aDumper.GetEnumerator;
aDumper := nil;
// - типа можно отпустить
try
l_Start := GetTickCount;
Assert(l_Enum <> nil);
while l_Enum.MoveNext do
if not DoHash(l_Enum.Current) then
break;
finally
l_Enum := nil;
end;//try..finally
finally
l_OutHash := nil;
end;//try..finally
finally
l_HashInfo := nil;
end;//try..finally
finally
if Assigned(aFilesMeter) then
aFilesMeter(piEnd, 0, '');
end;//try..finally
finally
l_OutIndex := nil;
end;//try..finally
//#UC END# *5B2E3DB902C7_5AEC481D0310_impl*
end;//m3MergeFromDumper
procedure m3CreateSummary(const aStorage: Im3IndexedStorage);
//#UC START# *5B2E42FB02E0_5AEC481D0310_var*
var
l_Stream : Il3Stream;
//#UC END# *5B2E42FB02E0_5AEC481D0310_var*
begin
//#UC START# *5B2E42FB02E0_5AEC481D0310_impl*
l_Stream := m3COMOpenStream(aStorage,
l3PCharLen(m3SummaryName),
m3_saWrite,
//m3_saReadWrite,
true);
l_Stream := nil;
//#UC END# *5B2E42FB02E0_5AEC481D0310_impl*
end;//m3CreateSummary
function m3DBMergeIndexDeltas(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc): Boolean;
//#UC START# *5B4F2446023E_5AEC481D0310_var*
var
l_DBHelper : Im3DBHelper;
l_E : Im3FilesEnumerable;
//#UC END# *5B4F2446023E_5AEC481D0310_var*
begin
//#UC START# *5B4F2446023E_5AEC481D0310_impl*
Result := false;
try
l_DBHelper := Tm3DBHelper.Make(aBaseName);
try
l_E := l_DBHelper.GetIndexDeltasFiles;
if not l_DBHelper.LockDeltas(l_E) then
begin
Result := false;
Exit;
end;//not l_DBHelper.Lock
try
Result := m3DBMergeIndexDeltas(l_DBHelper, l_E, aFilesMeter);
finally
l_DBHelper.UnlockDeltas;
end;//try..finally
finally
l_DBHelper := nil;
end;//try..finally
except
on E: Exception do
begin
l3System.Exception2Log(E);
Result := false;
end;//on E: Exception
else
Result := false;
end;//try..except
//#UC END# *5B4F2446023E_5AEC481D0310_impl*
end;//m3DBMergeIndexDeltas
function m3DBIndexUpdated(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aForceMerge: Boolean): Boolean;
//#UC START# *5B4F536603A6_5AEC481D0310_var*
var
l_WasUpdatedFile : Boolean;
function IndexUpdated: Boolean;
function MakeDB(const aName: String): Im3DB;
begin
Result := Tm3DB.Make(aName,
//cbMakeCopy.Checked AND cbFromOld.Checked,
nil,//Yield,
nil,//FileMeter.ProgressProc_ev,
aFilesMeter,//FilesMeter.ProgressProc_ev,
nil,//FilesProcessed,
nil //lProgressor.FilesProcessedExProc//FilesProcessedEx
);
end;
const
cDeleted = '%Deleted:';
var
l_DBHelper : Im3DBHelper;
l_Filer : Tl3CustomFiler;
l_Nums : Tm3StorageElementIDList;
l_S : AnsiString;
l_Num : Integer;
l_DB : Im3DB;
l_Range : Im3DBRange;
l_IndexName : Il3CString;
l_UpdatedFileName : String;
l_UpdatedFileNameBack : String;
l_E : Im3FilesEnumerable;
begin//IndexUpdated
Result := false;
l_DBHelper := Tm3DBHelper.Make(aBaseName);
try
l_E := l_DBHelper.GetIndexDeltasFiles;
if not l_DBHelper.LockDeltas(l_E) then
begin
Result := false;
Exit;
end;//not l_DBHelper.Lock
try
l_UpdatedFileName := aBaseName + '.updated';
if not FileExists(l_UpdatedFileName) then
begin
Result := true;
// - чтобы дальше дельта индексировалась
//Result := false;
Exit;
end;//not FileExists(l_UpdatedFileName)
l_WasUpdatedFile := true;
l_Nums := Tm3StorageElementIDList.Create;
try
l_Filer := Tl3DOSFiler.Make(l_UpdatedFileName, l3_fmRead, false);
try
l_Filer.Open;
try
while not l_Filer.EOF do
begin
l_S := l3PCharLen2String(l_Filer.ReadLn);
if (l_S <> '') then
begin
if AnsiStartsText('%', l_S) then
begin
if AnsiStartsText(cDeleted, l_S) then
begin
System.Delete(l_S, 1, Length(cDeleted));
if TryStrToInt(l_S, l_Num) then
begin
l_Nums.Add(l_Num);
end;//TryStrToInt(l_S, l_Num)
end;//AnsiStartsText(cDeleted, l_S)
end//AnsiStartsText('%', l_S)
else
begin
if TryStrToInt(l_S, l_Num) then
begin
l_Nums.Add(l_Num);
//break;
end;//TryStrToInt(l_S, l_Num)
end;//AnsiStartsText('%', l_S)
end;//l_S <> ''
end;//while not l_Filer.EOF
finally
l_Filer.Close;
end;//try..finally
finally
FreeAndNil(l_Filer);
end;//try..finally
if not l_Nums.Empty then
begin
l_DB := MakeDB(aBaseName);
try
l_Range := l_DB.FilesInList(l_Nums);
try
l_DB := nil;
l_IndexName := l_DBHelper.NewIndexDeltaName(l_E);
Result := m3IndexRange(l_Range, l_IndexName, true, aFilesMeter, l_DB) > 0;
if not Result then
Tm3StorageManager.DeleteStorageFile(l_IndexName)
else
l_DBHelper.AddNewIndexDeltaName(l_IndexName, l_E);
finally
l_Range := nil;
end;//try..finally
finally
l_DB := nil;
end;//try..finally
end//not l_Nums.Empty
else
Result := true;
// - чтобы дальше дельта индексировалась
finally
FreeAndNil(l_Nums);
end;//try..finally
if Result then
if (l_UpdatedFileName <> '') then
begin
l_UpdatedFileNameBack := l_UpdatedFileName + cBackExt;
SysUtils.DeleteFile(l_UpdatedFileNameBack);
SysUtils.RenameFile(l_UpdatedFileName, l_UpdatedFileNameBack);
//SysUtils.DeleteFile(l_UpdatedFileName);
end;//l_UpdatedFileName <> ''
finally
l_DBHelper.UnlockDeltas;
end;//try..finally
finally
l_DBHelper := nil;
end;//try..finally
end;//IndexUpdated
//#UC END# *5B4F536603A6_5AEC481D0310_var*
begin
//#UC START# *5B4F536603A6_5AEC481D0310_impl*
Result := false;
l_WasUpdatedFile := false;
if IndexUpdated then
begin
//Exit;
Result := true;
//l_WasUpdatedFile := false;
// - не объединяем дельты - пока не разберусь со скоростью.
if aForceMerge OR l_WasUpdatedFile then
begin
if m3DBBuildAndMergeIndexDeltas(aBaseName, aFilesMeter) then
begin
Result := true;
end;//m3DBBuildAndMergeIndexDeltas(aBaseName, aFilesMeter)
end//l_WasUpdatedFile
else
begin
if m3DBBuildIndexDelta(aBaseName, aFilesMeter, false, false{aForceFullIndex}) then
begin
Result := true;
end;//m3DBBuildIndexDelta(aBaseName, aFilesMeter, false, false)
end;//l_WasUpdatedFile
end;//IndexUpdated
//#UC END# *5B4F536603A6_5AEC481D0310_impl*
end;//m3DBIndexUpdated
function m3DBBuildAndMergeIndexDeltas(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc): Boolean;
//#UC START# *5B505AF40264_5AEC481D0310_var*
//#UC END# *5B505AF40264_5AEC481D0310_var*
begin
//#UC START# *5B505AF40264_5AEC481D0310_impl*
Result := false;
if m3DBBuildIndexDelta(aBaseName, aFilesMeter, false, false{aForceFullIndex}) then
begin
m3DBMergeIndexDeltas(aBaseName, aFilesMeter);
Result := true;
end;//m3DBBuildIndexDelta(l_N1, aFilesMeter, false, false)
//#UC END# *5B505AF40264_5AEC481D0310_impl*
end;//m3DBBuildAndMergeIndexDeltas
function m3DBMergeIndexDeltas(const aDBHelper: Im3DBHelper;
var aDeltas: Im3FilesEnumerable;
aFilesMeter: Tl3ProgressProc): Boolean;
//#UC START# *5B5087B00034_5AEC481D0310_var*
var
l_Attributes : Il3StringsEnumerable;
l_ContextAttributes : Il3StringsEnumerable;
l_UpdateName : Il3CString;
l_BaseName : TFileName;
function DoMerge: Boolean;
var
l_Full : Boolean;
procedure MergeText;
var
l_Dumper : Im3IndexDumper;
l_US : Boolean;
begin//MergeText
l_Dumper := Tm3IndexDumperJoin.MakeFromFiles(aDeltas);
try
if (l_Dumper <> nil) then
begin
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
m3MergeFromDumper(l_Dumper,
l_UpdateName,
not l_Full{true}, // - WriteVersions
aFilesMeter,
'' // - имя базы
);
l_Dumper := nil;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
Result := true;
end;//l_Dumper <> nil
finally
l_Dumper := nil;
end;//try..finally
end;//MergeText
var
l_AttrDeltas : Im3FilesEnumerable;
l_AttrUpdateName : Il3CString;
procedure MergeContextAttr;
var
l_ContextAttrDumper : Im3IndexDumper;
l_US : Boolean;
begin//MergeContextAttr
l_ContextAttrDumper := Tm3IndexDumperJoin.MakeFromFiles(l_AttrDeltas);
try
if (l_ContextAttrDumper <> nil) then
begin
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
m3MergeFromDumper(l_ContextAttrDumper,
l_AttrUpdateName,
not l_Full{true}, // - WriteVersions
aFilesMeter,
'' // - имя базы
);
l_ContextAttrDumper := nil;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end;//l_ContextAttrDumper <> nil
finally
l_ContextAttrDumper := nil;
end;//try..finally
end;//MergeContextAttr
var
l_IsDirect : Boolean;
procedure MergeAttr;
var
l_AttrDumper : Im3AttrIndexDumper;
l_US : Boolean;
begin//MergeAttr
l_AttrDumper := Tm3AttrIndexDumperJoin.MakeFromFiles(l_AttrDeltas, l_IsDirect);
try
if (l_AttrDumper <> nil) then
begin
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
Tm3AttrIndexDumper.MakeCopyFromDumper(l_AttrDumper,
l_AttrUpdateName,
not l_Full{true}, // - WriteVersions
aFilesMeter,
'',
l_IsDirect
);
l_AttrDumper := nil;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end;//l_AttrDumper <> nil
finally
l_AttrDumper := nil;
end;//try..finally
end;//MergeAttr
procedure MergeIntegerAttributes;
var
l_IsOurDirect : Boolean;
l_AttributesIt : Il3StringsEnumerator;
l_AttrBaseName : TFileName;
l_Count : Integer;
l_AttrDBHelper : Im3DBHelper;
begin//MergeIntegerAttributes
l_Count := 0;
//if (l_Count >= 2) then
begin
for l_IsOurDirect := false to true do
begin
l_IsDirect := l_IsOurDirect;
l_AttributesIt := l_Attributes.GetEnumerator;
if (l_AttributesIt <> nil) then
begin
while l_AttributesIt.MoveNext do
begin
l_AttrBaseName := Il3CString_ToFileName(Tm3AttrIndexDumperJoin.MakeNameForAttr(Il3CString_C(l_BaseName), l_AttributesIt.Current.AsString, l_IsDirect));
l_AttrDBHelper := Tm3DBHelper.Make(l_AttrBaseName);
try
l_AttrDBHelper.PurgeIndexDeltas;
l_AttrDeltas := l_AttrDBHelper.GetIndexDeltasFiles;
//l_AttrDeltas := Tm3AttrIndexDumperJoin.MakeFilesForAttr(aDeltas, l_AttributesIt.Current.AsString, l_IsDirect);
l_Count := l_AttrDeltas.Count;
if (l_Count >= 2) then
begin
if l_AttrDBHelper.TryLockDeltas(l_AttrDeltas) then
try
l_AttrUpdateName := l_AttrDBHelper.NewIndexDeltaName(l_AttrDeltas);
//l_AttrUpdateName := Tm3AttrIndexDumperJoin.MakeNameForAttr(l_UpdateName, l_AttributesIt.Current.AsString, l_IsDirect);
MergeAttr;
// - СПЕЦИАЛЬНО выделено в процедуру, чтобы интерфейсы ОСВОБОЖДАЛИСЬ
l_AttrDBHelper.PurgeIndexDeltas;
l_AttrDBHelper.DeleteIndexDeltas(l_AttrDeltas, true{false});
l_AttrDBHelper.AddNewIndexDeltaName(l_AttrUpdateName, l_AttrDeltas);
finally
l_AttrDBHelper.UnlockDeltas;
end;//try..finally
end;//l_Count >= 2
finally
l_AttrDBHelper := nil;
end;//try..finally
end;//while l_AttributesIt.MoveNext
end;//l_AttributesIt <> nil
end;//for l_IsDirect
end;//l_Count >= 2
end;//MergeIntegerAttributes
var
l_NeedMergeText : Boolean;
l_AttributesIt : Il3StringsEnumerator;
l_AttrBaseName : TFileName;
l_Count : Integer;
l_AttrDBHelper : Im3DBHelper;
begin//DoMerge
Result := false;
l_Full := false;
MergeIntegerAttributes;
// - https://mdp.garant.ru/pages/viewpage.action?pageId=902333600
l_Count := 0;
if (aDeltas <> nil) then
begin
l_Count := aDeltas.Count;
end;//aDeltas <> nil
if (l_Count >= 2) then
begin
l_NeedMergeText := not g_MergeOnlyAttributes;
if l_NeedMergeText then
begin
MergeText;
aDBHelper.DeleteIndexDeltas(aDeltas, true);
aDBHelper.AddNewIndexDeltaName(l_UpdateName, aDeltas);
end;//l_NeedMergeText
end;//l_Count >= 2
//if (l_Count >= 2) then
begin
l_AttributesIt := l_ContextAttributes.GetEnumerator;
if (l_AttributesIt <> nil) then
while l_AttributesIt.MoveNext do
begin
l_AttrBaseName := Il3CString_ToFileName(Tm3IndexDumperJoin.MakeNameForAttr(Il3CString_C(l_BaseName), l_AttributesIt.Current.AsString));
l_AttrDBHelper := Tm3DBHelper.Make(l_AttrBaseName);
try
l_AttrDBHelper.PurgeIndexDeltas;
l_AttrDeltas := l_AttrDBHelper.GetIndexDeltasFiles;
//l_AttrDeltas := Tm3IndexDumperJoin.MakeFilesForAttr(aDeltas, l_AttributesIt.Current.AsString);
l_Count := l_AttrDeltas.Count;
if (l_Count >= 2) then
begin
if l_AttrDBHelper.TryLockDeltas(l_AttrDeltas) then
try
l_AttrUpdateName := l_AttrDBHelper.NewIndexDeltaName(l_AttrDeltas);
//l_AttrUpdateName := Tm3IndexDumperJoin.MakeNameForAttr(l_UpdateName, l_AttributesIt.Current.AsString);
MergeContextAttr;
// - СПЕЦИАЛЬНО выделено в процедуру, чтобы интерфейсы ОСВОБОЖДАЛИСЬ
l_AttrDBHelper.PurgeIndexDeltas;
l_AttrDBHelper.DeleteIndexDeltas(l_AttrDeltas, true{false});
l_AttrDBHelper.AddNewIndexDeltaName(l_AttrUpdateName, l_AttrDeltas);
finally
l_AttrDBHelper.UnlockDeltas;
end;//try..finally
end;//l_Count >= 2
finally
l_AttrDBHelper := nil;
end;//try..finally
end;//while l_AttributesIt.MoveNext
end;//l_Count >= 2
MergeIntegerAttributes;
// - https://mdp.garant.ru/pages/viewpage.action?pageId=902333600
end;//DoMerge
var
l_Searcher : Im3AttrIndexSearcher;
//#UC END# *5B5087B00034_5AEC481D0310_var*
begin
//#UC START# *5B5087B00034_5AEC481D0310_impl*
Result := false;
l_BaseName := aDBHelper.BaseName;
aDBHelper.PurgeIndexDeltas;
l_Searcher := Tm3AttrIndexSearcher.Make(l_BaseName);
try
l_ContextAttributes := l_Searcher.ContextAttributesNames;
l_Attributes := l_Searcher.SearcheableAttributesNames;
l_UpdateName := aDBHelper.NewIndexDeltaName(aDeltas);
if DoMerge then
begin
Result := true;
end;//DoMerge
finally
l_Searcher := nil;
end;//try..finally
//#UC END# *5B5087B00034_5AEC481D0310_impl*
end;//m3DBMergeIndexDeltas
function m3DBUpdateIndex(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc): Boolean;
//#UC START# *5B60532E0383_5AEC481D0310_var*
var
l_ContextAttributes : Il3StringsEnumerable;
l_Attributes : Il3StringsEnumerable;
function DoDumper(const aDBHelper : Im3DBHelper; const aNewIndexName : Il3CString; const aDeltas: Im3FilesEnumerable): Boolean;
var
l_All : Im3FilesEnumerable;
procedure MergeText;
var
l_Dumper : Im3IndexDumper;
begin//MergeText
l_Dumper := Tm3IndexDumperJoin.MakeFromFiles(l_All);
if (l_Dumper <> nil) then
begin
try
m3MergeFromDumper(l_Dumper,
aNewIndexName,
false, // - WriteVersions
aFilesMeter,
aBaseName
);
l_Dumper := nil;
Result := true;
finally
l_Dumper := nil;
end;//try..finally
end;//l_DeltasDumper <> nil
end;//MergeText
var
l_AttrUpdateName : Il3CString;
l_AttrDeltas: Im3FilesEnumerable;
procedure MergeContextAttr;
var
l_ContextAttrDumper : Im3IndexDumper;
l_US : Boolean;
begin//MergeContextAttr
l_ContextAttrDumper := Tm3IndexDumperJoin.MakeFromFiles(l_AttrDeltas);
try
if (l_ContextAttrDumper <> nil) then
begin
Result := true;
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
m3MergeFromDumper(l_ContextAttrDumper,
l_AttrUpdateName,
false, // - WriteVersions
aFilesMeter,
aBaseName
);
l_ContextAttrDumper := nil;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end;//l_ContextAttrDumper <> nil
finally
l_ContextAttrDumper := nil;
end;//try..finally
end;//MergeContextAttr
var
l_IsDirect : Boolean;
procedure MergeAttr;
var
l_AttrDumper : Im3AttrIndexDumper;
l_US : Boolean;
begin//MergeAttr
l_AttrDumper := Tm3AttrIndexDumperJoin.MakeFromFiles(l_AttrDeltas, l_IsDirect);
try
if (l_AttrDumper <> nil) then
begin
Result := true;
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
Tm3AttrIndexDumper.MakeCopyFromDumper(l_AttrDumper,
l_AttrUpdateName,
false, // - WriteVersions
aFilesMeter,
aBaseName,
l_IsDirect
);
l_AttrDumper := nil;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
end;//l_AttrDumper <> nil
finally
l_AttrDumper := nil;
end;//try..finally
end;//MergeAttr
const
cTimeDelta = 14 * 60 * 60 * 1000;
// - 14 часов
var
l_Start : Cardinal;
function MergeIntegerAttributes: Boolean;
var
l_IsOurDirect : Boolean;
l_AttributesIt : Il3StringsEnumerator;
l_AttrBaseName : TFileName;
l_AttrDBHelper: Im3DBHelper;
l_NeedJoin : Boolean;
l_IndexMainFiles : Im3FilesEnumerable;
l_IndexMainFilesCount : Integer;
l_AttrDeltasForDelete: Im3FilesEnumerable;
begin//MergeIntegerAttributes
Result := true;
l_NeedJoin := false;
for l_IsOurDirect := false to true do
begin
l_IsDirect := l_IsOurDirect;
l_AttributesIt := l_Attributes.GetEnumerator;
if (l_AttributesIt <> nil) then
begin
while l_AttributesIt.MoveNext do
begin
l_AttrBaseName := Il3CString_ToFileName(Tm3AttrIndexDumperJoin.MakeNameForAttr(Il3CString_C(aBaseName), l_AttributesIt.Current.AsString, l_IsDirect));
l_AttrDBHelper := Tm3DBHelper.Make(l_AttrBaseName);
try
l_AttrDBHelper.PurgeIndexDeltas;
l_NeedJoin := false;
l_AttrDeltas := l_AttrDBHelper.GetAllIndexFiles;
l_AttrDeltasForDelete := l_AttrDBHelper.GetIndexDeltasFiles;
// - тут надо снимать, чтобы не затереть чужое
if l_AttrDBHelper.TryLockDeltas(l_AttrDeltas) then
try
l_AttrUpdateName := l_AttrDBHelper.NewIndexName;
if (l_AttrDeltas.Count > 1) then
l_NeedJoin := true
else
begin
l_IndexMainFiles := l_AttrDBHelper.GetIndexMainFiles;
if (l_IndexMainFiles = nil) then
l_IndexMainFilesCount := 0
else
l_IndexMainFilesCount := l_IndexMainFiles.Count;
if (l_IndexMainFilesCount = 0)
AND (l_AttrDeltas.Count = 1) then
// - есть только ОДНА дельта, но нету индекса, эту дельту надо перемыть в индекс
// возможно стоит НЕ ПЕРЕМЫВАТЬ, а объявить дельту ИНДЕКСОМ (переименовать)
l_NeedJoin := true;
end;//l_AttrDeltas.Count > 1
if l_NeedJoin then
MergeAttr;
l_AttrDBHelper.PurgeIndexDeltas;
if l_NeedJoin then
begin
l_AttrDBHelper.SetNewIndexName(l_AttrUpdateName);
l_AttrDBHelper.DeleteIndexDeltas(l_AttrDeltasForDelete, true{false});
end;//l_NeedJoin
finally
l_AttrDBHelper.UnlockDeltas;
end;//try..finally
if l3IsTimeElapsed(l_Start, cTimeDelta) then
begin
l3System.Msg2Log('Прерываем по таймауту: ' + aBaseName);
Result := false;
Exit;
end;//l3IsTimeElapsed(l_Start, cTimeDelta)
finally
l_AttrDBHelper := nil;
end;//try..finally
end;//while l_AttributesIt.MoveNext
end;//l_AttributesIt <> nil
end;//for l_IsDirect
end;//MergeIntegerAttributes
var
l_AttributesIt : Il3StringsEnumerator;
l_AttrBaseName : TFileName;
l_AttrDBHelper: Im3DBHelper;
l_IndexMainFiles : Im3FilesEnumerable;
l_IndexMainFilesCount : Integer;
l_NewIndexName : Il3CString;
l_Deltas: Im3FilesEnumerable;
l_AttrDeltasForDelete: Im3FilesEnumerable;
l_NeedMergeText : Boolean;
l_NeedJoin : Boolean;
begin//DoDumper
Result := false;
l_NeedJoin := false;
l_Start := GetTickCount;
// - новая точка отсчёта
if not MergeIntegerAttributes then
Exit;
l_All := aDBHelper.GetAllIndexFiles;
if (l_All <> nil) then
begin
if (l_All.Count > 1) then
// - есть что объединять
begin
l_NeedMergeText := not g_MergeOnlyAttributes;
if l_NeedMergeText then
begin
MergeText;
l_NewIndexName := aNewIndexName;
aDBHelper.SetNewIndexName(l_NewIndexName);
l_Deltas := aDeltas;
aDBHelper.DeleteIndexDeltas(l_Deltas, true);
end;//l_NeedMergeText
if l3IsTimeElapsed(l_Start, cTimeDelta) then
begin
l3System.Msg2Log('Прерываем по таймауту: ' + aBaseName);
Exit;
end;//l3IsTimeElapsed(l_Start, cTimeDelta)
end;//l_All.Count > 1
end;//l_All <> nil
l_AttributesIt := l_ContextAttributes.GetEnumerator;
if (l_AttributesIt <> nil) then
begin
while l_AttributesIt.MoveNext do
begin
l_AttrBaseName := Il3CString_ToFileName(Tm3IndexDumperJoin.MakeNameForAttr(Il3CString_C(aBaseName), l_AttributesIt.Current.AsString));
l_AttrDBHelper := Tm3DBHelper.Make(l_AttrBaseName);
try
l_AttrDBHelper.PurgeIndexDeltas;
l_NeedJoin := false;
l_AttrDeltas := l_AttrDBHelper.GetAllIndexFiles;
l_AttrDeltasForDelete := l_AttrDBHelper.GetIndexDeltasFiles;
// - тут надо снимать, чтобы не затереть чужое
if l_AttrDBHelper.TryLockDeltas(l_AttrDeltas) then
try
l_AttrUpdateName := l_AttrDBHelper.NewIndexName;
if (l_AttrDeltas.Count > 1) then
l_NeedJoin := true
else
begin
l_IndexMainFiles := l_AttrDBHelper.GetIndexMainFiles;
if (l_IndexMainFiles = nil) then
l_IndexMainFilesCount := 0
else
l_IndexMainFilesCount := l_IndexMainFiles.Count;
if (l_IndexMainFilesCount = 0)
AND (l_AttrDeltas.Count = 1) then
// - есть только ОДНА дельта, но нету индекса, эту дельту надо перемыть в индекс
// возможно стоит НЕ ПЕРЕМЫВАТЬ, а объявить дельту ИНДЕКСОМ (переименовать)
l_NeedJoin := true;
end;//l_AttrDeltas.Count > 1
if l_NeedJoin then
MergeContextAttr;
l_AttrDBHelper.PurgeIndexDeltas;
if l_NeedJoin then
begin
l_AttrDBHelper.SetNewIndexName(l_AttrUpdateName);
l_AttrDBHelper.DeleteIndexDeltas(l_AttrDeltasForDelete, true{false});
end;//l_NeedJoin
finally
l_AttrDBHelper.UnlockDeltas;
end;//try..finally
if l3IsTimeElapsed(l_Start, cTimeDelta) then
begin
l3System.Msg2Log('Прерываем по таймауту: ' + aBaseName);
Exit;
end;//l3IsTimeElapsed(l_Start, cTimeDelta)
finally
l_AttrDBHelper := nil;
end;//try..finally
end;//while l_AttributesIt.MoveNext
end;//l_AttributesIt <> nil
if not MergeIntegerAttributes then
Exit;
end;//DoDumper
var
l_UpdateName : Il3CString;
l_DBHelper : Im3DBHelper;
var
l_E : Im3FilesEnumerable;
// - вообще-то надо будет переделать на @l_All
l_FN : TFileName;
l_Ext : TFileName;
l_Searcher : Im3AttrIndexSearcher;
l_IndexName : Il3CString;
l_WasIndex : Boolean;
//#UC END# *5B60532E0383_5AEC481D0310_var*
begin
//#UC START# *5B60532E0383_5AEC481D0310_impl*
Result := false;
try
l_DBHelper := Tm3DBHelper.Make(aBaseName);
try
l_IndexName := l_DBHelper.IndexName;
l_WasIndex := Tm3StorageManager.StorageFileExists(l_IndexName);
m3DBIndexUpdated(aBaseName, aFilesMeter, not l_WasIndex);
{$If Defined(nsTest) OR Defined(m3DBCheck)}
Tm3StorageHolderList.DropAllFiles;
// - это тут зачем?
// Видимо потому же:
// - давайте всё отпустим, чтобы например с ЕО не подраться
{$IfEnd}
finally
l_DBHelper := nil;
end;//try..finally
l_DBHelper := Tm3DBHelper.Make(aBaseName);
try
l_E := l_DBHelper.GetIndexDeltasFiles;
if not l_DBHelper.LockDeltas(l_E) then
begin
Result := false;
Exit;
end;//not l_DBHelper.Lock
try
l_DBHelper.PurgeIndexDeltas;
l_UpdateName := l_DBHelper.NewIndexName;
l_Searcher := Tm3AttrIndexSearcher.Make(aBaseName);
try
l_ContextAttributes := l_Searcher.ContextAttributesNames;
l_Attributes := l_Searcher.SearcheableAttributesNames;
if DoDumper(l_DBHelper, l_UpdateName, l_E) then
begin
Result := true;
end//DoDumper
else
begin
l_FN := Il3CString_ToFileName(l_UpdateName);
if not g_IndexByParts then
begin
l_Ext := ExtractFileExt(l_FN);
if (l_Ext = '.idx') then
// - это я после этго добавил: https://mdp.garant.ru/pages/viewpage.action?pageId=893780516
Result := true
else
if (l_Ext = '.idx001') then
// - строили ПОЛНЫЙ индекс НЕ частями
Result := true;
// - нечего нам объединять
end;//not g_IndexByParts
end;//DoDumper
finally
l_Searcher := nil;
end;//try..finally
finally
l_DBHelper.UnlockDeltas;
end;//try..finally
finally
l_DBHelper := nil;
end;//try..finally
except
on E: Exception do
begin
l3System.Exception2Log(E);
Result := false;
end;//on E: Exception
else
Result := false;
end;//try..except
//#UC END# *5B60532E0383_5AEC481D0310_impl*
end;//m3DBUpdateIndex
function m3ReadModified(const aStorage: Im3IndexedStorage): Il3RangeEnumerable;
//#UC START# *5B7C17530137_5AEC481D0310_var*
var
l_S : Il3Stream;
//#UC END# *5B7C17530137_5AEC481D0310_var*
begin
//#UC START# *5B7C17530137_5AEC481D0310_impl*
l_S := m3COMOpenStream(aStorage,
l3PCharLen('modified'),
m3_saRead,
false);
try
Result := Il3RangeEnumerable_CreateFromStream(l_S);
finally
l_S := nil;
end;//try..finally
//#UC END# *5B7C17530137_5AEC481D0310_impl*
end;//m3ReadModified
procedure m3WriteModified(const aStorage: Im3IndexedStorage;
const aModified: Il3RangeEnumerable;
aTimeStamp: TDateTime);
//#UC START# *6602D7070340_5AEC481D0310_var*
var
l_Stream : IStream;
l_Now : TDateTime;
//#UC END# *6602D7070340_5AEC481D0310_var*
begin
//#UC START# *6602D7070340_5AEC481D0310_impl*
if (aModified <> nil) AND not aModified.Empty then
begin
l_Stream := m3COMOpenStream(aStorage,
l3PCharLen('modified'),
m3_saWrite,
//m3_saReadWrite,
true{false}).As_IStream;
try
Il3RangeEnumerable_WriteTo(aModified, l_Stream);
finally
l_Stream := nil;
end;//try..finally
if SameValue(aTimeStamp, BadDateTime) then
l_Now := Tl3TimeService.Instance.NowStamp
else
l_Now := aTimeStamp;
l_Stream := m3COMOpenStream(aStorage,
l3PCharLen('timestamp'),
m3_saWrite,
//m3_saReadWrite,
true{false}).As_IStream;
try
m2COMWriteBuffer(l_Stream, l_Now, SizeOf(l_Now));
finally
l_Stream := nil;
end;//try..finally
end;//(aModified <> nil) AND not aModified.Empty
//#UC END# *6602D7070340_5AEC481D0310_impl*
end;//m3WriteModified
procedure m3DBWaitIndexer;
//#UC START# *6881D6690242_5AEC481D0310_var*
//#UC END# *6881D6690242_5AEC481D0310_var*
begin
//#UC START# *6881D6690242_5AEC481D0310_impl*
if (g_IndexDocThread <> nil) then
begin
if not g_IndexDocThreadstarted then
Exit;
//g_IndexDocThread.Terminate;
Sleep(50);
//Sleep(500);
if (g_IndexDocThread <> nil) then
begin
{$IfDef Linux}
g_IndexDocThread.WaitFor;
{$Else Linux}
g_IndexDocThread.WaitFor;
{$EndIf Linux}
end;//g_IndexDocThread <> nil
end;//g_IndexDocThread <> nil
//#UC END# *6881D6690242_5AEC481D0310_impl*
end;//m3DBWaitIndexer
function m3DBIndexDoc(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aDocNum: Integer): Boolean;
//#UC START# *6881D7680046_5AEC481D0310_var*
function MakeDB(const aName: String): Im3DB;
begin
Result := Tm3DB.Make(aName,
//cbMakeCopy.Checked AND cbFromOld.Checked,
nil,//Yield,
nil,//FileMeter.ProgressProc_ev,
aFilesMeter,//FilesMeter.ProgressProc_ev,
nil,//FilesProcessed,
nil //lProgressor.FilesProcessedExProc//FilesProcessedEx
);
end;
var
l_Nums : Tm3StorageElementIDList;
l_IndexName : Il3CString;
l_E : Im3FilesEnumerable;
l_DBHelper : Im3DBHelper;
l_DB : Im3DB;
l_Range : Im3DBRange;
l_US : Boolean;
//#UC END# *6881D7680046_5AEC481D0310_var*
begin
//#UC START# *6881D7680046_5AEC481D0310_impl*
l_DBHelper := Tm3DBHelper.Make(aBaseName);
try
l_E := l_DBHelper.GetIndexDeltasFiles;
if not l_DBHelper.LockDeltas(l_E) then
begin
Result := false;
Exit;
end;//not l_DBHelper.Lock
try
l_Nums := Tm3StorageElementIDList.Create;
try
l_Nums.Add(aDocNum);
if not l_Nums.Empty then
begin
l_DB := MakeDB(aBaseName);
try
l_Range := l_DB.FilesInList(l_Nums);
try
l_DB := nil;
l_IndexName := l_DBHelper.NewIndexDeltaName(l_E);
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
Result := m3IndexRange(l_Range, l_IndexName, true, aFilesMeter, l_DB) > 0;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
if not Result then
Tm3StorageManager.DeleteStorageFile(l_IndexName)
else
l_DBHelper.AddNewIndexDeltaName(l_IndexName, l_E);
finally
l_Range := nil;
end;//try..finally
finally
l_DB := nil;
end;//try..finally
end//not l_Nums.Empty
else
Result := true;
// - чтобы дальше дельта индексировалась
finally
FreeAndNil(l_Nums);
end;//try..finally
finally
l_DBHelper.UnlockDeltas;
end;//try..finally
finally
l_DBHelper := nil;
end;//try..finally
//#UC END# *6881D7680046_5AEC481D0310_impl*
end;//m3DBIndexDoc
function m3DBIndexDocs(const aBaseName: TFileName;
aFilesMeter: Tl3ProgressProc;
aDocNums: Tl3IntegerList): Boolean;
//#UC START# *6881D86A00A2_5AEC481D0310_var*
function MakeDB(const aName: String): Im3DB;
begin
Result := Tm3DB.Make(aName,
//cbMakeCopy.Checked AND cbFromOld.Checked,
nil,//Yield,
nil,//FileMeter.ProgressProc_ev,
aFilesMeter,//FilesMeter.ProgressProc_ev,
nil,//FilesProcessed,
nil //lProgressor.FilesProcessedExProc//FilesProcessedEx
);
end;
var
l_Nums : Tm3StorageElementIDList;
l_IndexName : Il3CString;
l_E : Im3FilesEnumerable;
l_DBHelper : Im3DBHelper;
l_DB : Im3DB;
l_Range : Im3DBRange;
l_US : Boolean;
l_It : Il3IntegerEnumerator;
//#UC END# *6881D86A00A2_5AEC481D0310_var*
begin
//#UC START# *6881D86A00A2_5AEC481D0310_impl*
l_DBHelper := Tm3DBHelper.Make(aBaseName);
try
l_E := l_DBHelper.GetIndexDeltasFiles;
if not l_DBHelper.LockDeltas(l_E) then
begin
Result := false;
Exit;
end;//not l_DBHelper.Lock
try
l_Nums := Tm3StorageElementIDList.Create;
try
l_It := aDocNums.GetEnumerator;
if (l_It <> nil) then
while l_It.MoveNext do
l_Nums.Add(l_It.Current);
if not l_Nums.Empty then
begin
l_DB := MakeDB(aBaseName);
try
l_Range := l_DB.FilesInList(l_Nums);
try
l_DB := nil;
l_IndexName := l_DBHelper.NewIndexDeltaName(l_E);
l_US := Tm3StorageService.Instance.SetUseSplitted(false);
try
Result := m3IndexRange(l_Range, l_IndexName, true, aFilesMeter, l_DB) > 0;
finally
Tm3StorageService.Instance.SetUseSplitted(l_US);
end;//try..finally
if not Result then
Tm3StorageManager.DeleteStorageFile(l_IndexName)
else
l_DBHelper.AddNewIndexDeltaName(l_IndexName, l_E);
finally
l_Range := nil;
end;//try..finally
finally
l_DB := nil;
end;//try..finally
end//not l_Nums.Empty
else
Result := true;
// - чтобы дальше дельта индексировалась
finally
FreeAndNil(l_Nums);
end;//try..finally
finally
l_DBHelper.UnlockDeltas;
end;//try..finally
finally
l_DBHelper := nil;
end;//try..finally
//#UC END# *6881D86A00A2_5AEC481D0310_impl*
end;//m3DBIndexDocs
procedure m3DBIndexDocAsync(const aBaseName: TFileName;
aDocNum: Integer);
//#UC START# *6881D8A1027E_5AEC481D0310_var*
//#UC END# *6881D8A1027E_5AEC481D0310_var*
begin
//#UC START# *6881D8A1027E_5AEC481D0310_impl*
Tm3DBIndexDocThread.Run(aBaseName, aDocNum);
//m3DBIndexDoc(aBaseName, nil, aDocNum);
//#UC END# *6881D8A1027E_5AEC481D0310_impl*
end;//m3DBIndexDocAsync
procedure m3DBNeedIndexDoc(const aBaseName: TFileName;
aDocNum: Integer);
//#UC START# *6881D8E90347_5AEC481D0310_var*
//#UC END# *6881D8E90347_5AEC481D0310_var*
begin
//#UC START# *6881D8E90347_5AEC481D0310_impl*
m3DBIndexDocAsync(aBaseName, aDocNum);
// - возможно тут будем выбирать между m3DBIndexDocAsync и m3DBIndexUpdatedAsync
// в зависимости от наличия залочек.
// А возможно надо сделать Thread, которая будет крутиться ожидая LockDeltas.
//#UC END# *6881D8E90347_5AEC481D0310_impl*
end;//m3DBNeedIndexDoc
procedure m3DBIndexUpdatedAsync(const aBaseName: TFileName);
//#UC START# *6881D90B0256_5AEC481D0310_var*
var
l_T : TThread;
//#UC END# *6881D90B0256_5AEC481D0310_var*
begin
//#UC START# *6881D90B0256_5AEC481D0310_impl*
l_T := Tm3DBIndexUpdatedThread.Create(aBaseName);
l_T.Resume;
//m3DBIndexUpdated(aBaseName, nil, false);
//#UC END# *6881D90B0256_5AEC481D0310_impl*
end;//m3DBIndexUpdatedAsync
procedure m3SetInternalIDtoExternalIDLink(const aBaseName: TFileName;
anInternalID: Integer;
anExternalID: Integer);
{* Устанавливает связь между внутренним номером документа и внешним
https://mdp.garant.ru/pages/viewpage.action?pageId=892273772 }
//#UC START# *68D3E25E00B1_5AEC481D0310_var*
var
l_Searcher : Im3AttrIndexSearcher;
l_Internal : Integer;
l_External : Integer;
//l_BaseNameForAttr : TFileName;
l_NeedIndex : Boolean;
l_Builder : Tm3DocumentAttrIndexBuilder;
l_Range : Tm3IDRange;
l_A : Tm3AttrID;
l_Op : Tm3GroupOperation;
l_M : Tm3RangedDocumentsList;
l_BN : TFileName;
l_V : Tl3IntegerToIntegerMap;
l_DB : Im3DB;
//#UC END# *68D3E25E00B1_5AEC481D0310_var*
begin
//#UC START# *68D3E25E00B1_5AEC481D0310_impl*
Assert(anInternalID > 0);
Assert(anExternalID > 0);
l_NeedIndex := false;
l_DB := Tm3DB.Make(aBaseName);
try
l_Searcher := Tm3AttrIndexSearcher.Make(l_DB);
//l_Searcher := Tm3AttrIndexSearcher.Make(aBaseName);
try
l_External := -1;
l_Internal := l_Searcher.ExternalHandleToInternalHandle(anExternalID);
if (l_Internal = anInternalID) then
begin
// - связь есть
l_External := l_Searcher.InternalHandleToExternalHandle(anInternalID);
if (l_External = anExternalID) then
// - проверяем в ОБЕ стороны
Exit;
end;//l_Internal = anInternalID
l_NeedIndex := true;
(* with Tm3ExternalIDtoInternalIDMap.Instance do
begin
Lock;
try
l_NeedIndex := false;
if not Has(anExternalID) then
begin
Add(anExternalID, anInternalID);
// Тут ещё индексировать будем:
l_NeedIndex := true;
end//not Has(anExternalID)
else
begin
if (ValueSlotByKey(anExternalID)^ <> anInternalID) then
begin
ValueSlotByKey(anExternalID)^ := anInternalID;
// Тут ещё индексировать будем (замену):
l_NeedIndex := true;
end;//ValueSlotByKey(anExternalID)^ <> anInternalID
end;//not Has(anExternalID)
finally
Unlock;
end;//try..finally
end;//with Tm3ExternalIDtoInternalIDMap.Instance*)
if l_NeedIndex then
begin
//l_BaseNameForAttr := Il3CString_ToFileName(Tm3AttrIndexDumperJoin.MakeNameForAttr(Il3CString_C(aBaseName), Tk2Attributes.Instance.NameByID(k2_tiExternalHandle)));
l_Range := Tl3Range_C(anInternalID);
l_A := Tm3AttrID_C(k2_tiExternalHandle, '');
l_Op := m3_gopSet;
l_M := Tm3RangedDocumentsList.Create;
try
l_M.Add(anInternalID);
l_V := nil;
l_BN := aBaseName + '.idxdelta';
l_Builder := Tm3DocumentAttrIndexBuilder.Create(l_BN, l_A, l_M.AsEnumerable, l_V, @l_Range, false, l_Op, l_DB);
try
l_Builder.AddHandle(anInternalID, anExternalID);
l_Builder.Save;
finally
FreeAndNil(l_Builder);
end;//try..finally
l_Builder := Tm3DocumentAttrIndexBuilder.Create(l_BN, l_A, l_M.AsEnumerable, l_V, @l_Range, true, l_Op, l_DB);
try
l_Builder.AddHandle(anExternalID, anInternalID);
l_Builder.Save;
finally
FreeAndNil(l_Builder);
end;//try..finally
finally
FreeAndNil(l_M);
end;//try..finally
end;//l_NeedIndex
finally
l_Searcher := nil;
end;//try..finally
finally
l_DB := nil;
end;//try..finally
//#UC END# *68D3E25E00B1_5AEC481D0310_impl*
end;//m3SetInternalIDtoExternalIDLink
procedure m3WriteModified(const aStorage: Im3IndexedStorage;
const aModified: Il3RangeEnumerable);
//#UC START# *68EAABFC012B_5AEC481D0310_var*
//#UC END# *68EAABFC012B_5AEC481D0310_var*
begin
//#UC START# *68EAABFC012B_5AEC481D0310_impl*
m3WriteModified(aStorage, aModified, BadDateTime);
//#UC END# *68EAABFC012B_5AEC481D0310_impl*
end;//m3WriteModified
procedure m3WriteStringToDocument(const aDB: Im3DB;
aDocID: Integer;
anAttrID: Integer;
const aString: Tl3WString);
//#UC START# *68F083AE00D4_5AEC481D0310_var*
var
l_S : Tl3Str;
l_Doc : Im3DBDocument;
l_DocStream : IStream;
//#UC END# *68F083AE00D4_5AEC481D0310_var*
begin
//#UC START# *68F083AE00D4_5AEC481D0310_impl*
Assert(aDB <> nil);
if (anAttrID < 0) then
Exit;
if (anAttrID > k2_tiLast) then
Exit;
l_Doc := aDB.GetDocument(aDocID);
if (l_Doc <> nil) then
begin
try
l_DocStream := l_Doc.Open(m3_saWrite, m3_dsNames, anAttrID);
except
on Em3NoStreamForWrite do
l_DocStream := nil;
end;//try..except
try
if (l_DocStream <> nil) then
begin
if not l3IsNil(aString) then
begin
l_S.Init(aString, CP_Unicode);
try
m2COMWriteBuffer(l_DocStream, l_S.S^, l_S.SLen * SizeOf(WideChar));
finally
l_S.Clear;
end;//try..finally
end;//not l3IsNil(aString)
end;//l_DocStream <> nil
finally
l_DocStream := nil;
end;//try..finally
end;//l_Doc <> nil
//#UC END# *68F083AE00D4_5AEC481D0310_impl*
end;//m3WriteStringToDocument
constructor Tm3FilteredRange.Create(aVersions: Tl3IntegerToIntegerMap;
const anOther: Im3DBRange);
//#UC START# *5B06E840019F_5B06E7C7009D_var*
//#UC END# *5B06E840019F_5B06E7C7009D_var*
begin
//#UC START# *5B06E840019F_5B06E7C7009D_impl*
Assert(aVersions <> nil);
Assert(anOther <> nil);
inherited Create;
aVersions.SetRefTo(f_Versions);
f_Other := anOther;
//#UC END# *5B06E840019F_5B06E7C7009D_impl*
end;//Tm3FilteredRange.Create
class function Tm3FilteredRange.MakePrim(aVersions: Tl3IntegerToIntegerMap;
const anOther: Im3DBRange): Im3DBRange;
var
l_Inst : Tm3FilteredRange;
begin
l_Inst := Create(aVersions, anOther);
try
Result := l_Inst;
finally
l_Inst.Free;
end;//try..finally
end;//Tm3FilteredRange.MakePrim
class function Tm3FilteredRange.Make(aVersions: Tl3IntegerToIntegerMap;
const anOther: Im3DBRange): Im3DBRange;
//#UC START# *5B5080160141_5B06E7C7009D_var*
//#UC END# *5B5080160141_5B06E7C7009D_var*
begin
//#UC START# *5B5080160141_5B06E7C7009D_impl*
if (aVersions = nil) OR aVersions.Empty then
Result := anOther
else
Result := MakePrim(aVersions, anOther);
//#UC END# *5B5080160141_5B06E7C7009D_impl*
end;//Tm3FilteredRange.Make
{$If NOT Defined(l3NoSRT)}
function Tm3FilteredRange.SetRefTo(var thePlace: Tm3FilteredRange): Boolean;
begin
if (thePlace = Self) then
Result := false
else
begin
Result := true;
thePlace.Free;
thePlace := Self.Use;
end;//thePlace = Self
end;//Tm3FilteredRange.SetRefTo
{$IfEnd} // NOT Defined(l3NoSRT)
function Tm3FilteredRange.DB: Im3DB;
//#UC START# *4720847C026F_5B06E7C7009D_var*
//#UC END# *4720847C026F_5B06E7C7009D_var*
begin
//#UC START# *4720847C026F_5B06E7C7009D_impl*
Result := f_Other.DB;
//#UC END# *4720847C026F_5B06E7C7009D_impl*
end;//Tm3FilteredRange.DB
function Tm3FilteredRange.Mul(const aRange: Im3DBRange): Im3DBRange;
{* Пересекает выборки. }
//#UC START# *472718E303CA_5B06E7C7009D_var*
//#UC END# *472718E303CA_5B06E7C7009D_var*
begin
//#UC START# *472718E303CA_5B06E7C7009D_impl*
Result := Self;
Assert(false);
//#UC END# *472718E303CA_5B06E7C7009D_impl*
end;//Tm3FilteredRange.Mul
{$If NOT Defined(m3NoEVD)}
function Tm3FilteredRange.Iterate(const aFilter: Im3TagGenerator;
aNeedWriteToBase: Boolean;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
//#UC START# *472719650005_5B06E7C7009D_var*
//#UC END# *472719650005_5B06E7C7009D_var*
begin
//#UC START# *472719650005_5B06E7C7009D_impl*
Result := m3IterateRangeViaFilter(Self, aFilter, aNeedWriteToBase, aParts, Self.DB);
//#UC END# *472719650005_5B06E7C7009D_impl*
end;//Tm3FilteredRange.Iterate
{$IfEnd} // NOT Defined(m3NoEVD)
function Tm3FilteredRange.IterateF(anAction: Tm3FilerAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
//#UC START# *47271A4301A1_5B06E7C7009D_var*
var
l_Count : Integer absolute Result;
function DoFiler(aFiler: Tl3CustomFiler; const anIndex : Tm3DBStreamIndex): Boolean;
var
l_IDSource : Im3VersionedStorageElementIDSource;
l_ID : Tm3VersionedStorageElementID;
l_Ver : Integer;
l_Index : Integer;
begin//DoFiler
if Supports(aFiler.COMStream, Im3VersionedStorageElementIDSource, l_IDSource) then
try
l_ID := l_IDSource.VersionedID;
if f_Versions.Has(l_ID.rID, l_Index) then
begin
l_Ver := f_Versions.ItemSlot(l_Index).rValue;
if (l_Ver = l_ID.rVersion) then
begin
Result := true;
Exit;
end;//l_Ver = l_ID.rVersion
end;//f_Versions.Has(l_ID.rID.rID, l_Index)
finally
l_IDSource := nil;
end;//try..finally
Result := anAction(aFiler, anIndex);
if Result then
Inc(l_Count);
end;//DoFiler
//#UC END# *47271A4301A1_5B06E7C7009D_var*
begin
//#UC START# *47271A4301A1_5B06E7C7009D_impl*
Result := 0;
try
{Result := }f_Other.IterateF(m3L2FilerAction(@DoFiler), aParts);
//Result := Iterate(anAction, aParts);
finally
m3FreeFilerAction(anAction);
end;//try..finally
//#UC END# *47271A4301A1_5B06E7C7009D_impl*
end;//Tm3FilteredRange.IterateF
function Tm3FilteredRange.IterateF(anAction: Tm3DocumentAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
//#UC START# *47271A8703B1_5B06E7C7009D_var*
//#UC END# *47271A8703B1_5B06E7C7009D_var*
begin
//#UC START# *47271A8703B1_5B06E7C7009D_impl*
try
Result := 0;
Assert(false);
//Result := Iterate(anAction, aParts);
finally
m3FreeDocumentAction(anAction);
end;//try..finally
//#UC END# *47271A8703B1_5B06E7C7009D_impl*
end;//Tm3FilteredRange.IterateF
function Tm3FilteredRange.CopyTo(const aDB: Im3DB;
aMode: Tm3DBCopyMode = m3_cmRewrite;
const aParts: Tm3DocPartSet = m3_AllDocParts): Boolean;
{* переливает выборку в другую базу. }
//#UC START# *47271A9E01AC_5B06E7C7009D_var*
//#UC END# *47271A9E01AC_5B06E7C7009D_var*
begin
//#UC START# *47271A9E01AC_5B06E7C7009D_impl*
Result := false;
Assert(false);
//#UC END# *47271A9E01AC_5B06E7C7009D_impl*
end;//Tm3FilteredRange.CopyTo
procedure Tm3FilteredRange.Cleanup;
{* Функция очистки полей объекта. }
//#UC START# *479731C50290_5B06E7C7009D_var*
//#UC END# *479731C50290_5B06E7C7009D_var*
begin
//#UC START# *479731C50290_5B06E7C7009D_impl*
FreeAndNil(f_Versions);
inherited;
//#UC END# *479731C50290_5B06E7C7009D_impl*
end;//Tm3FilteredRange.Cleanup
procedure Tm3FilteredRange.ClearFields;
begin
f_Other := nil;
inherited;
end;//Tm3FilteredRange.ClearFields
constructor Tm3SubRange.Create(aFrom: Integer;
aMaxLen: Integer;
const anOther: Im3DBRange);
//#UC START# *5DA721EF0369_5DA721C700EC_var*
//#UC END# *5DA721EF0369_5DA721C700EC_var*
begin
//#UC START# *5DA721EF0369_5DA721C700EC_impl*
Assert(anOther <> nil);
f_Other := anOther;
f_From := aFrom;
f_MaxLen := aMaxLen;
f_Last := f_From;
inherited Create;
//#UC END# *5DA721EF0369_5DA721C700EC_impl*
end;//Tm3SubRange.Create
class function Tm3SubRange.Make(aFrom: Integer;
aMaxLen: Integer;
const anOther: Im3DBRange): Im3DBRange;
var
l_Inst : Tm3SubRange;
begin
l_Inst := Create(aFrom, aMaxLen, anOther);
try
Result := l_Inst;
finally
l_Inst.Free;
end;//try..finally
end;//Tm3SubRange.Make
{$If NOT Defined(l3NoSRT)}
function Tm3SubRange.SetRefTo(var thePlace: Tm3SubRange): Boolean;
begin
if (thePlace = Self) then
Result := false
else
begin
Result := true;
thePlace.Free;
thePlace := Self.Use;
end;//thePlace = Self
end;//Tm3SubRange.SetRefTo
{$IfEnd} // NOT Defined(l3NoSRT)
function Tm3SubRange.DB: Im3DB;
//#UC START# *4720847C026F_5DA721C700EC_var*
//#UC END# *4720847C026F_5DA721C700EC_var*
begin
//#UC START# *4720847C026F_5DA721C700EC_impl*
Result := f_Other.DB;
//#UC END# *4720847C026F_5DA721C700EC_impl*
end;//Tm3SubRange.DB
function Tm3SubRange.Mul(const aRange: Im3DBRange): Im3DBRange;
{* Пересекает выборки. }
//#UC START# *472718E303CA_5DA721C700EC_var*
//#UC END# *472718E303CA_5DA721C700EC_var*
begin
//#UC START# *472718E303CA_5DA721C700EC_impl*
Result := Self;
Assert(false);
//#UC END# *472718E303CA_5DA721C700EC_impl*
end;//Tm3SubRange.Mul
{$If NOT Defined(m3NoEVD)}
function Tm3SubRange.Iterate(const aFilter: Im3TagGenerator;
aNeedWriteToBase: Boolean;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
//#UC START# *472719650005_5DA721C700EC_var*
//#UC END# *472719650005_5DA721C700EC_var*
begin
//#UC START# *472719650005_5DA721C700EC_impl*
Result := m3IterateRangeViaFilter(Self, aFilter, aNeedWriteToBase, aParts, Self.DB);
//#UC END# *472719650005_5DA721C700EC_impl*
end;//Tm3SubRange.Iterate
{$IfEnd} // NOT Defined(m3NoEVD)
function Tm3SubRange.IterateF(anAction: Tm3FilerAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
//#UC START# *47271A4301A1_5DA721C700EC_var*
var
l_Count : Integer absolute Result;
l_PrevID : Integer;
l_Len : Integer;
function DoFiler(aFiler: Tl3CustomFiler; const anIndex : Tm3DBStreamIndex): Boolean;
var
l_ID : Integer;
begin//DoFiler
l_ID := anIndex.rID;
if (l_ID < f_From) then
begin
Result := true;
Exit;
end;//l_ID < f_From
if (l_ID <> l_PrevID) then
begin
Inc(l_Len);
if (l_Len >= f_MaxLen) then
begin
Result := false;
Exit;
end;//l_Len >= f_MaxLen
end;//l_ID <> l_PrevID
Result := anAction(aFiler, anIndex);
if Result then
begin
l_PrevID := l_ID;
Inc(l_Count);
end;//Result
end;//DoFiler
//#UC END# *47271A4301A1_5DA721C700EC_var*
begin
//#UC START# *47271A4301A1_5DA721C700EC_impl*
Result := 0;
try
l_PrevID := -1;
l_Len := 0;
{Result := }f_Other.IterateF(m3L2FilerAction(@DoFiler), aParts);
if (l_PrevID = -1) then
// - ни разу не попали
f_Last := High(Integer)
else
if (l_Len < f_MaxLen) AND not f_Other.DB.Stopped then
f_Last := High(Integer)
else
f_Last := l_PrevID + 1;
//Result := Iterate(anAction, aParts);
finally
m3FreeFilerAction(anAction);
end;//try..finally
//#UC END# *47271A4301A1_5DA721C700EC_impl*
end;//Tm3SubRange.IterateF
function Tm3SubRange.IterateF(anAction: Tm3DocumentAction;
const aParts: Tm3DocPartSet = m3_AllDocParts): Integer;
//#UC START# *47271A8703B1_5DA721C700EC_var*
//#UC END# *47271A8703B1_5DA721C700EC_var*
begin
//#UC START# *47271A8703B1_5DA721C700EC_impl*
try
Result := 0;
Assert(false);
//Result := Iterate(anAction, aParts);
finally
m3FreeDocumentAction(anAction);
end;//try..finally
//#UC END# *47271A8703B1_5DA721C700EC_impl*
end;//Tm3SubRange.IterateF
function Tm3SubRange.CopyTo(const aDB: Im3DB;
aMode: Tm3DBCopyMode = m3_cmRewrite;
const aParts: Tm3DocPartSet = m3_AllDocParts): Boolean;
{* переливает выборку в другую базу. }
//#UC START# *47271A9E01AC_5DA721C700EC_var*
//#UC END# *47271A9E01AC_5DA721C700EC_var*
begin
//#UC START# *47271A9E01AC_5DA721C700EC_impl*
Result := false;
Assert(false);
//#UC END# *47271A9E01AC_5DA721C700EC_impl*
end;//Tm3SubRange.CopyTo
procedure Tm3SubRange.Cleanup;
{* Функция очистки полей объекта. }
//#UC START# *479731C50290_5DA721C700EC_var*
//#UC END# *479731C50290_5DA721C700EC_var*
begin
//#UC START# *479731C50290_5DA721C700EC_impl*
f_Other := nil;
inherited;
//#UC END# *479731C50290_5DA721C700EC_impl*
end;//Tm3SubRange.Cleanup
procedure Tm3SubRange.ClearFields;
begin
f_Other := nil;
inherited;
end;//Tm3SubRange.ClearFields
//#UC START# *5DA721C700ECimpl*
procedure IndexDocThreadWait;
{$IfDef Linux}
(*var
l_Count : Integer;
l_Then : TDateTime;*)
{$EndIf Linux}
begin//IndexDocThreadWait
if (g_IndexDocThread <> nil) then
begin
if not g_IndexDocThreadstarted then
Exit;
//g_IndexDocThread.Terminate;
{$IfDef Linux}
g_IndexDocThread.WaitFor;
(* l_Then := Now;
l_Count := 0;
while (g_IndexDocThread <> nil) do
begin
Sleep(100);
//Sleep(1000);
Inc(l_Count);
if (l_Count > 60) then
//if (l_Count > 1000) then
break;
if (MinutesBetween(Now, l_Then) > 5) then
break;
end;//g_IndexDocThread <> nil*)
{$Else Linux}
g_IndexDocThread.WaitFor;
{$EndIf Linux}
end;//g_IndexDocThread <> nil
end;//IndexDocThreadWait
constructor Tm3DBIndexDocThread.Create(const aBaseName : TFileName; aDocNum : Integer);
begin
if (g_IndexDocThread = nil) then
begin
if not g_IndexDocThreadWaitAdded then
begin
g_IndexDocThreadWaitAdded := true;
Tl3MemUtils.AddExitProc(IndexDocThreadWait);
end;//not g_IndexDocThreadWaitAdded
g_IndexDocThread := Self;
end;//g_IndexDocThread = nil
inherited Create(true);
f_BaseName := aBaseName;
f_DocNum := aDocNum;
Self.FreeOnTerminate := true;
//Self.Resume;
end;
destructor Tm3DBIndexDocThread.Destroy;
begin
inherited;
l3System.EnterGlobalCS;
try
FreeAndNil(f_DocNums);
if (g_IndexDocThread = Self) then
begin
g_IndexDocThread := nil;
g_IndexDocThreadstarted := false;
end;//g_IndexDocThread = Self
finally
l3System.LeaveGlobalCS;
end;//try..finally
end;
class procedure Tm3DBIndexDocThread.Run(const aBaseName : TFileName; aDocNum : Integer);
var
l_T : TThread;
begin
l3System.EnterGlobalCS;
try
if (g_IndexDocThread = nil) then
begin
l_T := Self.Create(aBaseName, aDocNum);
l_T.Resume;
end//g_IndexDocThread = nil
else
begin
if (g_IndexDocThread.f_DocNums = nil) then
g_IndexDocThread.f_DocNums := Tl3IntegerList.Create;
g_IndexDocThread.f_DocNums.Add(aDocNum);
end;//g_IndexDocThread = nil
finally
l3System.LeaveGlobalCS;
end;//try..finally
end;
procedure Tm3DBIndexDocThread.Execute;
var
l_DocNums : Tl3IntegerList;
l_DBHelper : Im3DBHelper;
l_E : Im3FilesEnumerable;
l_P : Tl3ProgressProc;
begin
try
if (g_IndexDocThread = Self) then
g_IndexDocThreadstarted := true;
m3DBIndexDoc(f_BaseName, nil, f_DocNum);
l_DocNums := nil;
while true do
begin
begin
// Асинхронно запускать объединение дельт. Если их типа много накопилось.
// m3DBMergeIndexDeltas
l_DBHelper := Tm3DBHelper.Make(f_BaseName);
try
l_E := l_DBHelper.GetIndexDeltasFiles;
if (l_E <> nil) then
if (l_E.Count > 5) then
begin
l_P := nil;
m3DBMergeIndexDeltas(f_BaseName, l_P);
end;//l_E.Count > 5
finally
l_DBHelper := nil;
end;//try..finally
end;
if (f_DocNums <> nil) then
begin
l3System.EnterGlobalCS;
try
if (f_DocNums <> nil) then
begin
if not f_DocNums.Empty then
begin
f_DocNums.SetRefTo(l_DocNums);
FreeAndNil(f_DocNums);
end;//not f_DocNums.Empty
end;//f_DocNums <> nil
finally
l3System.LeaveGlobalCS;
end;//try..finally
end;//f_DocNums <> nil
if (l_DocNums <> nil) then
begin
try
if not l_DocNums.Empty then
begin
m3DBIndexDocs(f_BaseName, nil, l_DocNums);
continue;
end;//not l_DocNums.Empty
finally
FreeAndNil(l_DocNums);
end;//try..finally
end;//l_DocNums <> nil
break;
end;//while true
except
if (g_IndexDocThread = Self) then
g_IndexDocThread := nil;
end;//try..except
end;
constructor Tm3DBIndexUpdatedThread.Create(const aBaseName : TFileName);
begin
inherited Create(true);
f_BaseName := aBaseName;
Self.FreeOnTerminate := true;
//Self.Resume;
end;
procedure Tm3DBIndexUpdatedThread.Execute;
begin
m3DBIndexUpdated(f_BaseName, nil, false);
end;
//#UC END# *5DA721C700ECimpl*
//#UC START# *5AEC481D0310impl*
//#UC END# *5AEC481D0310impl*
//#UC START# *5AEC481D0310forDiagramm*
(*
*)
//#UC END# *5AEC481D0310forDiagramm*
end.
Комментариев нет:
Отправить комментарий